Java定时调度任务详解之Timer篇

简单介绍

什么是定时任务调度
    基于给定的时间点,给定的时间间隔,或者给定的执行次数自动执行的任务。
Java中定时调度工具
    Timer  ---〉 jdk
    Quartz --〉 第三方jar包,实现更完善。
    尽量使用jdk提供的timer

Timer简介

    有且仅有一个后台线程对多个业务线程进行定时定频率的调度。
主要构件

    Timer 可以理解为每个后台执行的线程,TimerTask业务线程
Timer工具类详解


第一个简单实例
import java.util.TimerTask;

public class MyTaskTimer extends TimerTask {
	
	private String name;
	
	public MyTaskTimer(String name) {
		this.name = name;
	}

	@Override
	public void run() {
            System.out.println("Current name is: " + name);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
测试类
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		//3、通过timer定时定频率调用myTimerTask的业务逻辑
		// 即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
		timer.schedule(myTaskTimer, 2000L, 1000L);
	}
	
}

Timer的定时调度函数

schedule(task, time)
    task --> 所要安排的任务
    在时间等于或超过time的时候执行且仅执行一次task
实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimerTask;

public class MyTaskTimer extends TimerTask {

	private String name;

	public MyTaskTimer(String name) {
		this.name = name;
	}

	@Override
	public void run() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("current exect time:" + sf.format(calendar.getTime()));
		System.out.println("Current name is: " + name);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

测试类
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		
		/**
		 * 获取当前时间,并设置成距离当前时间三秒之后的时间
		 */
		Calendar calendar = Calendar.getInstance();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sf.format(calendar.getTime()));
		calendar.add(Calendar.SECOND, 3);//设置三秒之后的时间
		
		myTaskTimer.setName("schedule1");
		timer.schedule(myTaskTimer, calendar.getTime());
	}
	
}
schedule(task, time, period)
    task     --> 所要安排的任务
    time     -->首次执行任务的时间
    period  -->执行一次task的时间间隔,单位是毫秒
    时间等于或超过time时首次执行task,之后每隔period毫秒重复执行一次task
测试类
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		
		/**
		 * 获取当前时间,并设置成距离当前时间三秒之后的时间
		 */
		Calendar calendar = Calendar.getInstance();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sf.format(calendar.getTime()));
		calendar.add(Calendar.SECOND, 3);//设置三秒之后的时间
		
		myTaskTimer.setName("schedule2");
		timer.schedule(myTaskTimer, calendar.getTime(), 2000);//执行3秒钟之后的时间
	}
	
}

schedule(task, delay)
    task   --> 所要安排的任务
    delay --> 执行任务前的延时时间,单位毫秒
    等待delay毫秒后执行且仅执行一次task
实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		
		/**
		 * 获取当前时间,并设置成距离当前时间三秒之后的时间
		 */
		Calendar calendar = Calendar.getInstance();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sf.format(calendar.getTime()));
		calendar.add(Calendar.SECOND, 3);//设置三秒之后的时间
		
		myTaskTimer.setName("schedule3");
		timer.schedule(myTaskTimer, 2000);//执行3秒钟之后的时间
	}
	
}
schedule(task, delay, period)
    task   --> 所要安排的任务
    delay --> 执行任务前的延时时间,单位毫秒
    period  -->执行一次task的时间间隔,单位是毫秒
    等待delay毫秒后首次执行task,之后每隔period毫秒重复执行一次task
实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		
		/**
		 * 获取当前时间,并设置成距离当前时间三秒之后的时间
		 */
		
		myTaskTimer.setName("schedule4");
		Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sf.format(calendar.getTime()));calendar.add(Calendar.SECOND, 3);//设置三秒之后的时间myTaskTimer.setName("schedule4");timer.schedule(myTaskTimer, 2000, 2000);//执行3秒钟之后的时间}}

scheduleAtFixedRate的两种用法
scheduleAtFixedRate(task, time, period)
    task     --> 所要安排的任务
    time     -->首次执行任务的时间
    period  -->执行一次task的时间间隔,单位是毫秒
    时间等于或超过time时首次执行task,之后每隔period毫秒重复执行一次task




实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		
		/**
		 * 获取当前时间,并设置成距离当前时间三秒之后的时间
		 */
		Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sf.format(calendar.getTime()));
		calendar.add(Calendar.SECOND, 3);//设置三秒之后的时间
		
		myTaskTimer.setName("scheduleAtFixedRate1");
		timer.scheduleAtFixedRate(myTaskTimer, calendar.getTime(), 2000);//执行3秒钟之后的时间
	}
	
}
scheduleAtFixedRate(task, delay, period)
    task   --> 所要安排的任务
    delay --> 执行任务前的延时时间,单位毫秒
    period  -->执行一次task的时间间隔,单位是毫秒
    等待delay毫秒后首次执行task,之后每隔period毫秒重复执行一次task
实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		
		/**
		 * 获取当前时间,并设置成距离当前时间三秒之后的时间
		 */
		Calendar calendar = Calendar.getInstance();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sf.format(calendar.getTime()));
		calendar.add(Calendar.SECOND, 3);//设置三秒之后的时间
		
		myTaskTimer.setName("scheduleAtFixedRate2");
		timer.scheduleAtFixedRate(myTaskTimer, 3000, 2000);//距离当前时间3秒钟
	}
	
}

其它重要函数

cancel()
取消当前TimerTask里的任务
实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimerTask;

public class MyTaskTimer extends TimerTask {

	private String name;
	
	private Integer count = 0;

	public MyTaskTimer(String name) {
		this.name = name;
	}

	@Override
	public void run() {
		if (count < 3) {
			Calendar calendar = Calendar.getInstance();
	                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	                System.out.println("current exect time:" + sf.format(calendar.getTime()));
			System.out.println("Current name is: " + name);	
			count ++;
		} else {
			cancel();
			System.out.println("Task Cancle");
		}
        
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
测试类
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		
		/**
		 * 获取当前时间,并设置成距离当前时间三秒之后的时间
		 */
		Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sf.format(calendar.getTime()));
		calendar.add(Calendar.SECOND, 3);//设置三秒之后的时间
		
		myTaskTimer.setName("schedule");
		timer.schedule(myTaskTimer, 3000, 2000);//距离当前时间3秒钟
	}
	
}
scheduleExecutionTime()
    返回此任务最近实际执行的已安排执行的时间,返回值为最近发生此任务执行安排的时间,为long型
实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 1、创建一个Timer实例
		Timer timer = new Timer();
		//2、创建一个MyTimerTask实例
		MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
		
		/**
		 * 获取当前时间,并设置成距离当前时间三秒之后的时间
		 */
		Calendar calendar = Calendar.getInstance();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sf.format(calendar.getTime()));
		calendar.add(Calendar.SECOND, 3);//设置三秒之后的时间
		
		myTaskTimer.setName("schedule");
		timer.schedule(myTaskTimer, 3000);//距离当前时间3秒钟,只执行一次
		
		System.out.println("schedule time is :" + sf.format(myTaskTimer.scheduledExecutionTime()));
	}
	
}

Timer下的cancel()
    终止此计时器,丢弃所有当前已安排的任务

实例:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;

public class CancleTest {

	public static void main(String[] args) throws InterruptedException {
		//创建一个Timer实例
		Timer timer = new Timer();
		//创建TaskTimer实例
		MyTaskTimer task1 = new MyTaskTimer("task1");
		MyTaskTimer task2 = new MyTaskTimer("task2");
		//获取当前时间并打印
		Date startDate = new Date();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("start time is :" + sf.format(startDate));
		
		timer.schedule(task1, 3000L, 2000L);
		timer.schedule(task2, 1000L, 2000L);
		//休眠5秒
		Thread.sleep(5000L);
		//获取当前时间并打印
		Date cancelTime = new Date();
		System.out.println("cancel time is :" + sf.format(cancelTime));
		//取消所有任务
		timer.cancel();
		System.out.println("Tasks all canceled");
	}
}
Timer下的purge()
从此计时器的任务队列中移除所有已取消的任务,返回值 从队列中移除的任务数
实例
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;

public class CancleTest {

	public static void main(String[] args) throws InterruptedException {
		//创建一个Timer实例
		Timer timer = new Timer();
		//创建TaskTimer实例
		MyTaskTimer task1 = new MyTaskTimer("task1");
		MyTaskTimer task2 = new MyTaskTimer("task2");
		//获取当前时间并打印
		Date startDate = new Date();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("start time is :" + sf.format(startDate));
		
		timer.schedule(task1, 3000L, 2000L);
		timer.schedule(task2, 1000L, 2000L);
		System.out.println("current canceled task number is:" + timer.purge());
		//休眠2秒
		Thread.sleep(2000L);
		//获取当前时间并打印
		Date cancelTime = new Date();
		System.out.println("cancel time is :" + sf.format(cancelTime));
		//取消task2的任务
		task2.cancel();
		System.out.println("current canceled task number is:" + timer.purge());
	}
}

schedule和scheduleAtFixRate区别

schedule方法
    “fixed-delay” ;如果第一次执行时间被delay,随后的执行时间按照上一次实际完成的时间点进行计算.
实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class DifferenceTest {

	public static void main(String[] args) {
		final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar calendar = Calendar.getInstance();
		System.out.println("current time is : " + sf.format(calendar.getTime()));
		//设置成6秒的时间,若当前时间为2017-11-11 00:00:06
		//那么设置之后的时间变成2017-11-11 00:00:00
		calendar.add(Calendar.SECOND, -6);
		Timer timer = new Timer();
		//第一次执行时间为6秒前,之后每隔两秒钟执行一次
		timer.schedule(new TimerTask() {
			
			@Override
			public void run() {
				//打印当前计划执行时间
				System.out.println("schedule exect time is:" + sf.format(scheduledExecutionTime()));
				System.out.println("Task is being exected");
			}
		},calendar.getTime(), 2000L);
	}
}

scheduleAtFixRate方法
    “fixed-rate” ;如果第一次执行时间被delay了,随后的执行时间按照上一次开始的时间点进行计算,并且为了赶上进度会多次执行任务,因此TimerTask中的执行体需要考虑同步

任务执行时间超出执行时间间隔
schedule方法
    下一次执行时间相对于上一次实际执行完成的是时间点,因此执行时间会不断延后。
实例
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class DifferenceTest {

	public static void main(String[] args) {
		final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar calendar = Calendar.getInstance();
		System.out.println("current time is : " + sf.format(calendar.getTime()));
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(3000L);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//打印当前计划执行时间
				System.out.println("schedule exect time is:" + sf.format(scheduledExecutionTime()));
				System.out.println("Task is being exected");
			}
		},calendar.getTime(), 2000L);
	}
}
scheduleAtFixRate方法
    下一次执行时间相对于上一次开始的时间点,因此执行时间不会延后,因此存在并发性。

实际应用

import java.text.SimpleDateFormat;
import java.util.TimerTask;
/**
 * 跳舞机器人,每隔两秒钟跳舞
 */
public class DancingRobot extends TimerTask {

	@Override
	public void run() {
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("Scheduled exec time is : "
				+ sf.format(scheduledExecutionTime()));
		System.out.println("Dancing happily");
	}

}
import java.util.Timer;
import java.util.TimerTask;
/**
 * 灌水机器人,水注入满5升后,等待两秒钟后,取消所有
 * @author lijingyu
 *
 */
public class WaterRobot extends TimerTask {

	private Timer timer;
	private Integer bucketCapacity = 0;
	
	public WaterRobot(Timer inputTimer) {
		timer = inputTimer;
	}
	
	@Override
	public void run() {

		if (bucketCapacity < 5) {
			System.out.println("Add 1L water into the bucket!");
			bucketCapacity ++;
		} else {
			System.out.println("The number of canceled task in timer is :" + timer.purge());
			//水满后停止
			cancel();
			System.out.println("The WaterRobot has bean aborted!");
			System.out.println("The number of canceled task in timer is :" + timer.purge());
			System.out.println("Current water is " + bucketCapacity + "L");
			try {
				Thread.sleep(2000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			timer.cancel();//取消所有
		}
	}

}
执行机器人
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class ExectorRobot {

	public static void main(String[] args) {
		Timer timer = new Timer();
		//获取当前时间
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("Current time is" + sf.format(calendar.getTime()));
		
		DancingRobot dr = new DancingRobot();
		WaterRobot wr = new WaterRobot(timer);
		
		timer.schedule(dr, calendar.getTime(), 2000L);
		timer.scheduleAtFixedRate(wr, calendar.getTime(), 1000L);
	}
	
}

Timer缺陷

管理并发任务的缺陷
    Timer有且仅有一个线程去执行定时任务,如果存在多个任务,且任务时间过长,会导致执行效果与预期不符。

当任务抛出异常时缺陷
    如果TimerTask抛出RuntimeException,Timer会停止所有任务的运行。
Timer的使用禁区
    对时效性要求较高的多任务并发作业;对复杂的任务调度。

参考

     慕课网

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值