Timer类主要负责计划任务,即在指定时间执行某一个任务。TimerTask是一个抽象类,进行封装任务。
创建一个Timer就是启动一个新的线程,默认的新启动的线程不是守护线程,它会一直运行,要使它变成守护线程,则Timer timer=new Timer(true)即可。
一、schedule方法
1.当执行任务的时间晚于当前的时间,则任务会等到执行任务的计划时间再运行。
2.当执行任务的时间早于当前的时间,则会立即执行task的任务。
3.多个task任务执行
TimeTask是以队列的方式一个一个顺序的执行,当前面的任务消耗时间过长时,后面的任务的运行时间也会被延迟。
Run3.java
/*
* TimeTask是以队列的方式一个一个被顺序执行,所以执行的时间可能不一致
* 前面的任务有可能消耗时间比较长导致后面任务运行的时间也会被延迟。
*
*/
public class Run3 {
static private Timer timer=new Timer();
static public class MyTesk1 extends TimerTask{
@Override
public void run() {
try{
System.out.println("1 begin! "+new Date());
Thread.sleep(20000);
System.out.println("1 end! "+new Date());
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
static public class MyTesk2 extends TimerTask{
@Override
public void run() {
System.out.println("2 begin! "+new Date());
System.out.println("运行了,时间为:"+new Date());
System.out.println("2 end! "+new Date());
}
}
public static void main(String[] args){
try{
MyTesk1 task1=new MyTesk1();
MyTesk2 task2=new MyTesk2();
SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dataString1="2017-9-21 15:35:00";
String dataString2="2017-9-21 15:35:10";
Date dataRef1=sdf1.parse(dataString1);
Date dataRef2=sdf2.parse(dataString2);
System.out.println("字符串1时间为:"+dataRef1.toLocaleString()+" 当前时间为:"+new Date());
System.out.println("字符串2时间为:"+dataRef2.toLocaleString()+" 当前时间为:"+new Date());
timer.schedule(task1,dataRef1);
timer.schedule(task2, dataRef2);
}catch(ParseException e){
e.printStackTrace();
}
}
}
4.schedule(TimeTask task,Date firstTime,long period)
该方法是在指定的日期后,按照时间间隔周期性的无限循环的执行某一任务。
Run4.java
/*
* timer.schedule(taskA, dataRef,4000);
* 在指定的日期以后,按照指定的时间间隔周期性的无线循环某一任务,即使任务被延迟了,任务还是一个一个的顺序执行。
*/
public class Run4 {
//private static Timer timer=new Timer();
static public class MyTaskA extends TimerTask{
public void run(){
try{
System.out.println("A运行了!时间为:"+new Date());
Thread.sleep(5000);
System.out.println("A结束了!时间为:"+new Date());
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args){
try{
MyTaskA taskA=new MyTaskA();
Timer timer=new Timer();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dataString ="2017-9-21 16:05:00";
Date dataRef=sdf.parse(dataString);
System.out.println("字符串时间:"+dataRef.toLocaleString()+" 当前时间为:"+new Date());
timer.schedule(taskA, dataRef,4000);
}catch(ParseException e){
e.printStackTrace();
}
}
}
结果:
5.TimerTask类的cancel()方法和Timer类的cancel()方法
前者会把自身从任务队列中清除,不影响其他任务;后者会把队列中的所有任务清除,但是后者不一定会停止任务,因为可能cancel()没有争抢到queue锁。
Run5.java
/*
* TimeTask中的cancel()作用是把自身从任务中删除,不影响其他任务的执行
* Timer中的cancel()作用是将任务队列的所有任务都清空。
*
*/
public class Run5 {
private static Timer timer=new Timer();
static public class MyTaskA extends TimerTask{
public void run(){
System.out.println("A运行了!时间为:"+new Date());
//this.cancel();
timer.cancel();
}
}
static public class MyTaskB extends TimerTask{
public void run(){
System.out.println("B运行了!时间为:"+new Date());
}
}
public static void main(String[] args){
try{
MyTaskA taskA=new MyTaskA();
MyTaskB taskB=new MyTaskB();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString="2017-9-21 16:30:00";
//Timer timer=new Timer();
Date dateRef=sdf.parse(dateString);
System.out.println("字符串时间为:"+dateRef.toLocaleString()+" 当前时间为:"+new Date());
timer.schedule(taskA, dateRef,4000);
timer.schedule(taskB, dateRef,4000);
//timer.cancel();有时不一定会停止执行任务,因为有可能cancel()没有争抢到queue锁,所以队列中的任务继续执行,一旦得到,则任务结束。
}catch(ParseException e){
e.printStackTrace();
}
}
}
自己可以把相应的注释去掉进行实验验证。
6.schedule(TimerTask task,long delay)
以当前时间为参考时间,在此时间的基础上按延迟时间执行任务。
7.schedule(TimerTask task,long delay,long period)
以当前时间为参考时间,在此时间的基础上按延迟时间执行任务,再一period间隔无限次数的执行某一任务。
二、scheduleAtFixedRate方法
1.此方法基本和schedule是类似的,唯一不同就是在于不延时的情况。
Run6.java
/*
* 如果执行任务的时间没有被延迟,那么schedule下一次任务执行的时间是上一次任务开始的时间加上延时,scheduleAtFixedRate下一次任务的执行时间是以上一次任务的结束时间开始
* 如果执行任务的时间被延迟,则二者下一次任务的开始时间都是上一次任务的结束时间
*/
public class RUN6 {
private static Timer timer=new Timer();
private static int runcount=0;
static public class MyTask1 extends TimerTask{
public void run(){
try{
System.out.println("1 begin "+new Date());
Thread.sleep(2000);
System.out.println("1 end "+new Date());
runcount++;
if(runcount==5){
timer.cancel();
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public static void main(String[] args){
try{
MyTask1 task1=new MyTask1();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString="2017-9-21 16:51:00";
Date dateRef=sdf.parse(dateString);
System.out.println("字符串时间:"+dateRef.toLocaleString()+" 当前时间为:"+new Date());
timer.scheduleAtFixedRate(task1, dateRef, 3000);
//timer.schedule(task1, dateRef,3000);
}catch(ParseException e){
e.printStackTrace();
}
}
}
2.schedule和scheduleAtFixedRate另一个不同,关于追赶执行性。
Run7.java
/*
* schedule不具有追赶执行性,scheduleAtFixedRate具有追赶执行性
* 即当前时间晚于计划执行任务时间时,前者会忽略计划执行任务,直接从当前开始,
* 但是后者会一开始补充性的把当前时间到计划执行任务时间的这段时间内的任务先执行完,之后再开始正常执行。
*/
public class Run7 {
static private Timer timer=new Timer();
static public class MyTask extends TimerTask{
public void run(){
System.out.println("1 begin !"+new Date());
System.out.println("1 end !"+new Date());
}
}
public static void main(String[] args){
try{
MyTask task=new MyTask();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString ="2017-9-21 17:09:00";
Date dateRef=sdf.parse(dateString);
System.out.println("字符串时间为:"+dateRef.toLocaleString()+"当前时间为:"+new Date());
// timer.schedule(task, dateRef,10000);
timer.scheduleAtFixedRate(task, dateRef, 5000);
}catch(ParseException e){
e.printStackTrace();
}
}
}