Java多线程编程核心技术--定时器
来源:互联网 发布:2017网络综艺发展趋势 编辑:程序博客网 时间:2024/06/05 08:49
Timer类主要负责计划任务,也就是在指定的时间开始执行某一个任务。
方法schedule(TimerTask task, Date time)
public class Task { private static Timer timer = new Timer(); static public class MyTask extends TimerTask{ @Override public void run() { System.out.println("Task运行了,时间为:" + new Date()); } } public static void main(String[] args) { try { MyTask myTask = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = "2016-07-09 21:30:19"; Date date = sdf.parse(dateString); System.out.println("main启动时间为:" + new Date()); timer.schedule(myTask, date); } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main启动时间为:Sat Jul 09 21:28:54 CST 2016Task运行了,时间为:Sat Jul 09 21:30:19 CST 2016
任务虽然执行完了,但是进程还没有销毁。
创建Timer的源码如下:
public Timer() { this("Timer-" + serialNumber());} public Timer(String name) { thread.setName(name); thread.start();}
由构造方法可知,创建一个Timer就是启动一个新的线程,这个新启动的线程并不是守护线程,它就一直在运行。
将新创建的timer改成守护线程如下:
public class Task { private static Timer timer = new Timer(true); static public class MyTask extends TimerTask{ @Override public void run() { System.out.println("Task运行了,时间为:" + new Date()); } } public static void main(String[] args) { try { MyTask myTask = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = "2016-07-09 21:42:19"; Date date = sdf.parse(dateString); System.out.println("main启动时间为:" + new Date()); timer.schedule(myTask, date); } catch (Exception e) { e.printStackTrace(); } }}
此时控制台打印结果如下:
main启动时间为:Sat Jul 09 21:41:59 CST 2016
由于新创建的Timer线程是守护线程,main线程运行完成之后迅速结束当前进程的运行。TimerTask中的任务不会得到执行。
若执行任务的时间早于当前时间,则会立即执行任务。
public class Task { private static Timer timer = new Timer(); static public class MyTask extends TimerTask{ @Override public void run() { System.out.println("Task运行了,时间为:" + new Date()); } } public static void main(String[] args) { try { MyTask myTask = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = "2016-07-09 21:42:19"; Date date = sdf.parse(dateString); System.out.println("main启动时间为:" + new Date()); timer.schedule(myTask, date); } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main启动时间为:Sat Jul 09 21:47:29 CST 2016Task运行了,时间为:Sat Jul 09 21:47:29 CST 2016
多个TimerTask任务及延时的测试
Timer中允许有多个TimerTask任务
public class Task { private static Timer timer = new Timer(); static public class MyTask1 extends TimerTask{ @Override public void run() { System.out.println("Task1运行了,时间为:" + new Date()); } } static public class MyTask2 extends TimerTask{ @Override public void run() { System.out.println("Task2运行了,时间为:" + new Date()); } } public static void main(String[] args) { try { MyTask1 myTask1 = new MyTask1(); MyTask2 myTask2 = new MyTask2(); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString1 = "2016-07-09 22:04:19"; String dateString2 = "2016-07-09 22:05:19"; Date date1 = sdf1.parse(dateString1); Date date2 = sdf2.parse(dateString2); System.out.println("main启动时间为:" + new Date()); timer.schedule(myTask1, date1); timer.schedule(myTask2, date2); } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main启动时间为:Sat Jul 09 22:04:09 CST 2016Task1运行了,时间为:Sat Jul 09 22:04:19 CST 2016Task2运行了,时间为:Sat Jul 09 22:05:19 CST 2016
TimerTask是以队列的方式一个一个被顺序执行的,所以执行的时间有可能和预期的时间不一致。如果前面的任务耗时较长,后面的任务执行时间有可能被推迟。
public class Task { private static Timer timer = new Timer(); static public class MyTask1 extends TimerTask{ @Override public void run() { System.out.println("Task1运行了,时间为:" + new Date()); try { Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } } } static public class MyTask2 extends TimerTask{ @Override public void run() { System.out.println("Task2运行了,时间为:" + new Date()); } } public static void main(String[] args) { try { MyTask1 myTask1 = new MyTask1(); MyTask2 myTask2 = new MyTask2(); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString1 = "2016-07-09 22:08:19"; String dateString2 = "2016-07-09 22:08:29"; Date date1 = sdf1.parse(dateString1); Date date2 = sdf2.parse(dateString2); System.out.println("main启动时间为:" + new Date()); timer.schedule(myTask1, date1); timer.schedule(myTask2, date2); } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main启动时间为:Sat Jul 09 22:08:06 CST 2016Task1运行了,时间为:Sat Jul 09 22:08:19 CST 2016Task2运行了,时间为:Sat Jul 09 22:08:39 CST 2016
方法schedule(TimerTask task, Date firstTime, long period)
该方法的作用是在指定的日期之后,按指定的时间间隔周期性地无限循环地执行某一个任务
public class Main { static public class MyTask extends TimerTask{ @Override public void run() { System.out.println("开始运行,时间:" + new Date()); } public static void main(String[] args) { try { MyTask task = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Timer timer = new Timer(); String dateString = "2016-07-09 22:17:55"; Date date = sdf.parse(dateString); System.out.println("main开始执行时间:" + new Date()); timer.schedule(task, date, 4000); } catch (Exception e) { e.printStackTrace(); } } }}
程序执行结果如下:
main开始执行时间:Sat Jul 09 22:17:30 CST 2016开始运行,时间:Sat Jul 09 22:17:55 CST 2016开始运行,时间:Sat Jul 09 22:17:59 CST 2016开始运行,时间:Sat Jul 09 22:18:03 CST 2016开始运行,时间:Sat Jul 09 22:18:07 CST 2016......
TimerTask类的cancel()方法
TimerTask类的cancel()方法的作用是将自身从任务队列中清除
public class Task { private static Timer timer = new Timer(); static public class MyTask1 extends TimerTask{ @Override public void run() { System.out.println("Task1运行了,时间为:" + new Date()); this.cancel(); } } static public class MyTask2 extends TimerTask{ @Override public void run() { System.out.println("Task2运行了,时间为:" + new Date()); } } public static void main(String[] args) { try { MyTask1 myTask1 = new MyTask1(); MyTask2 myTask2 = new MyTask2(); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString1 = "2016-07-09 22:08:19"; String dateString2 = "2016-07-09 22:08:29"; Date date1 = sdf1.parse(dateString1); Date date2 = sdf2.parse(dateString2); System.out.println("main启动时间为:" + new Date()); timer.schedule(myTask1, date1, 4000); timer.schedule(myTask2, date2, 4000); } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main启动时间为:Sat Jul 09 22:24:15 CST 2016Task1运行了,时间为:Sat Jul 09 22:24:15 CST 2016Task2运行了,时间为:Sat Jul 09 22:24:15 CST 2016Task2运行了,时间为:Sat Jul 09 22:24:19 CST 2016Task2运行了,时间为:Sat Jul 09 22:24:23 CST 2016......
Timer类的cancel()方法
Timer类的cancel()方法的作用是将任务队列中的全部任务清除
public class Task { private static Timer timer = new Timer(); static public class MyTask1 extends TimerTask{ @Override public void run() { System.out.println("Task1运行了,时间为:" + new Date()); timer.cancel(); } } static public class MyTask2 extends TimerTask{ @Override public void run() { System.out.println("Task2运行了,时间为:" + new Date()); } } public static void main(String[] args) { try { MyTask1 myTask1 = new MyTask1(); MyTask2 myTask2 = new MyTask2(); SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString1 = "2016-07-09 22:08:19"; String dateString2 = "2016-07-09 22:08:29"; Date date1 = sdf1.parse(dateString1); Date date2 = sdf2.parse(dateString2); System.out.println("main启动时间为:" + new Date()); timer.schedule(myTask1, date1, 4000); timer.schedule(myTask2, date2, 4000); } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main启动时间为:Sat Jul 09 22:26:21 CST 2016Task1运行了,时间为:Sat Jul 09 22:26:21 CST 2016
全部任务都被清除,并且进程被销毁。
Timer类的cancel()方法注意事项
public class Main { static int i = 0; static public class MyTask extends TimerTask{ @Override public void run() { System.out.println("正常执行:" + i); } } public static void main(String[] args) throws ParseException { while (true) { i++; Timer timer = new Timer(); MyTask task = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = "2016-07-09 22:32:55"; Date date = sdf.parse(dateString); timer.schedule(task, date); timer.cancel(); } }}
程序运行结果如下:
......正常执行:12466正常执行:12486正常执行:12592正常执行:12656正常执行:12773正常执行:15554正常执行:15968......
这是因为Timer类中的cancel()没有争抢到queue锁,所以TimerTask类中的任务继续正常执行。
方法schedule(TimerTask task, long delay)的使用
方法schedule(TimerTask task, long delay)的作用是以当前时间为基准延迟delay毫秒数执行
public class Main { static public class MyTask extends TimerTask{ @Override public void run() { System.out.println("执行时间:" + new Date()); } } public static void main(String[] args) throws ParseException { Timer timer = new Timer(); MyTask task = new MyTask(); System.out.println("当前时间:" + new Date()); timer.schedule(task, 5000); }}
程序运行结果如下:
当前时间:Sat Jul 09 22:37:45 CST 2016执行时间:Sat Jul 09 22:37:50 CST 2016
schedule(task, delay, period)的使用
schedule(task, delay, period)的作用是以当前时间为基准延迟delay毫秒数,以period毫秒数为间隔无限循环周期执行
public class Main { static public class MyTask extends TimerTask{ @Override public void run() { System.out.println("执行时间:" + new Date()); } } public static void main(String[] args) throws ParseException { Timer timer = new Timer(); MyTask task = new MyTask(); System.out.println("当前时间:" + new Date()); timer.schedule(task, 5000, 2000); }}
程序运行结果如下:
当前时间:Sat Jul 09 22:40:14 CST 2016执行时间:Sat Jul 09 22:40:19 CST 2016执行时间:Sat Jul 09 22:40:21 CST 2016执行时间:Sat Jul 09 22:40:23 CST 2016......
schedule方法任务不延时
public class Main { private static Timer timer = new Timer(); private static int runCount = 0; static public class MyTask extends TimerTask{ @Override public void run() { try { System.out.println("begin run," + new Date()); Thread.sleep(1000); System.out.println("end run," + new Date()); runCount++; if (runCount == 5) { timer.cancel(); } } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { try { MyTask task = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = "2016-07-10 10:26:35"; Date date = sdf.parse(dateString); System.out.println("main开始时间:" + new Date()); timer.schedule(task, date, 3000); } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main开始时间:Sun Jul 10 10:26:27 CST 2016begin run,Sun Jul 10 10:26:35 CST 2016end run,Sun Jul 10 10:26:36 CST 2016begin run,Sun Jul 10 10:26:38 CST 2016end run,Sun Jul 10 10:26:39 CST 2016begin run,Sun Jul 10 10:26:41 CST 2016end run,Sun Jul 10 10:26:42 CST 2016begin run,Sun Jul 10 10:26:44 CST 2016end run,Sun Jul 10 10:26:45 CST 2016begin run,Sun Jul 10 10:26:47 CST 2016end run,Sun Jul 10 10:26:48 CST 2016
在不延时的情况下,如果执行任务的时间没有被延时,则下一次执行任务的时间是上一次任务的开始时间加上delay时间。
schedule方法任务延时
public class Main { private static Timer timer = new Timer(); private static int runCount = 0; static public class MyTask extends TimerTask{ @Override public void run() { try { System.out.println("begin run," + new Date()); Thread.sleep(5000);//任务耗时5秒 System.out.println("end run," + new Date()); runCount++; if (runCount == 5) { timer.cancel(); } } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { try { MyTask task = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = "2016-07-10 17:00:00"; Date date = sdf.parse(dateString); System.out.println("main开始时间:" + new Date()); timer.schedule(task, date, 3000);//周期为3秒 } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main开始时间:Sun Jul 10 16:59:31 CST 2016begin run,Sun Jul 10 17:00:00 CST 2016end run,Sun Jul 10 17:00:05 CST 2016begin run,Sun Jul 10 17:00:05 CST 2016end run,Sun Jul 10 17:00:10 CST 2016begin run,Sun Jul 10 17:00:10 CST 2016end run,Sun Jul 10 17:00:15 CST 2016begin run,Sun Jul 10 17:00:15 CST 2016end run,Sun Jul 10 17:00:20 CST 2016begin run,Sun Jul 10 17:00:20 CST 2016end run,Sun Jul 10 17:00:25 CST 2016
任务执行周期为3秒,任务每次执行耗时5秒。从运行结果看,如果执行任务的时间被延时,那么下一次任务的执行时间以上一次任务“结束”时的时间为参考来计算。
scheduleAtFixedRate方法任务不延时
public class Main { private static Timer timer = new Timer(); private static int runCount = 0; static public class MyTask extends TimerTask{ @Override public void run() { try { System.out.println("begin run," + new Date()); Thread.sleep(2000);//任务耗时2秒 System.out.println("end run," + new Date()); runCount++; if (runCount == 5) { timer.cancel(); } } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { try { MyTask task = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = "2016-07-10 17:18:00"; Date date = sdf.parse(dateString); System.out.println("main开始时间:" + new Date()); timer.scheduleAtFixedRate(task, date, 3000);//周期为3秒 } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main开始时间:Sun Jul 10 17:17:51 CST 2016begin run,Sun Jul 10 17:18:00 CST 2016end run,Sun Jul 10 17:18:02 CST 2016begin run,Sun Jul 10 17:18:03 CST 2016end run,Sun Jul 10 17:18:05 CST 2016begin run,Sun Jul 10 17:18:06 CST 2016end run,Sun Jul 10 17:18:08 CST 2016begin run,Sun Jul 10 17:18:09 CST 2016end run,Sun Jul 10 17:18:11 CST 2016begin run,Sun Jul 10 17:18:12 CST 2016end run,Sun Jul 10 17:18:14 CST 2016
==schedule和scheduleAtFixedRate的区别在于,如果指定开始执行的时间在当前系统运行时间之前,scheduleAtFixedRate会把已经过去的时间也作为周期执行,而schedule不会把过去的时间算上。==
scheduleAtFixedRate方法任务延时
public class Main5 { private static Timer timer = new Timer(); private static int runCount = 0; static public class MyTask extends TimerTask{ @Override public void run() { try { System.out.println("begin run," + new Date()); Thread.sleep(5000);//任务耗时5秒 System.out.println("end run," + new Date()); runCount++; if (runCount == 5) { timer.cancel(); } } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { try { MyTask task = new MyTask(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = "2016-07-10 17:21:40"; Date date = sdf.parse(dateString); System.out.println("main开始时间:" + new Date()); timer.scheduleAtFixedRate(task, date, 3000);//周期为3秒 } catch (Exception e) { e.printStackTrace(); } }}
程序运行结果如下:
main开始时间:Sun Jul 10 17:21:35 CST 2016begin run,Sun Jul 10 17:21:40 CST 2016end run,Sun Jul 10 17:21:45 CST 2016begin run,Sun Jul 10 17:21:45 CST 2016end run,Sun Jul 10 17:21:50 CST 2016begin run,Sun Jul 10 17:21:50 CST 2016end run,Sun Jul 10 17:21:55 CST 2016begin run,Sun Jul 10 17:21:55 CST 2016end run,Sun Jul 10 17:22:00 CST 2016begin run,Sun Jul 10 17:22:00 CST 2016end run,Sun Jul 10 17:22:05 CST 2016
任务开始时间间隔为5秒。
- Java多线程编程核心技术--定时器
- java多线程编程核心技术5-Timer定时器
- 《Java多线程编程核心技术》(五)定时器Timer的使用
- Java多线程编程核心技术(第五章定时器Timer笔记)
- 【java多线程编程核心技术】5.定时器Timer-笔记总结
- java多线程编程核心技术
- 《Java多线程编程核心技术》
- Java 多线程编程核心技术
- [Java多线程编程核心技术]
- 《java多线程编程核心技术》
- java多线程编程核心技术
- Java多线程编程核心技术
- java多线程编程核心技术
- Java多线程编程核心技术
- Java多线程核心技术(五):定时器Timer
- java多线程核心技术 第五章 定时器Timer
- 《Java多线程编程核心技术》推荐
- Java多线程编程核心技术笔记
- 寒假学习总结
- Java多线程编程核心技术---线程间通信(一)
- Java多线程编程核心技术---线程间通信(二)
- Java多线程编程核心技术--Lock的使用(一)
- Java多线程编程核心技术---单例模式与多线程
- Java多线程编程核心技术--定时器
- Java多线程编程核心技术---拾遗增补
- 获取当前时间和当年年度的元旦
- SVN同步到指定目录,windows环境下
- Android中的RelativeLayout中组件的排放问题
- Java备份约9亿条数据
- 欢迎使用CSDN-markdown编辑器
- 软删除脏数据job笔记
- linux(64/32) 下安装sqlite3