定时任务的说明

定时任务是一个使用概率不高,但是很大几率会使用到的功能,记录之。



/**
 * 任务的执行,依赖于Timer,可以特定的时间执行或者按照某种规律循环的执行
 * A facility for threads to schedule tasks for future execution in a background thread.
 * Tasks may be scheduled for one-time execution, or for repeated execution at regular intervals.
 *
 * 弊端:
 * 1. 不能针对某一个定时任务进行取消
 * 2. Timer 的设计核心是一个 TaskList 和一个 TaskThread。Timer 将接收到的任务丢到自己的 TaskList 中,
 * TaskList 按照 Task 的最初执行时间进行排序。TimerThread 在创建 Timer 时会启动成为一个守护线程。
 * 这个线程会轮询所有任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread 被唤醒并执行该任务。
 * 之后 TimerThread 更新最近一个要执行的任务,继续休眠。但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,
 * 同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。
 * */
public class TimerTest extends TimerTask {

	private String jobName = "";

	public TimerTest(String jobName) {
		super();
		this.jobName = jobName;
	}

	@Override
	public void run() {
		try {
			//如果一个线程执行的过程中休眠会影响其他的线程的执行
			Thread.sleep(100000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("execute " + jobName);
	}

	public static void main(String[] args) {
		Timer timer = new Timer();
		long delay1 = 1 * 1000;
		long period1 = 1000;
		// 从现在开始 1 秒钟之后,每隔 1 秒钟执行一次 job1
		timer.schedule(new TimerTest("job1"), delay1, period1);

		long delay2 = 2 * 1000;
		long period2 = 2000;
		// 从现在开始 2 秒钟之后,每隔 2 秒钟执行一次 job2
		timer.schedule(new TimerTask() {

			@Override
			public void run() {
				System.out.println("第二个线程的执行完毕!");
			}
		}, delay2, period2);

		//取消任务,则会取消全部的任务
//		timer.cancel();
	}
}

进化版:

public class ScheduledExecutorUtil {

	public static ScheduledExecutorUtil getInstance(){
		return ScheduledExecutorUtilHoler.instance;
	}

	private static class ScheduledExecutorUtilHoler{
		private static  ScheduledExecutorUtil instance = new ScheduledExecutorUtil();
	}
	private ScheduledThreadPoolExecutor scheduExec = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(10);;
	private ConcurrentHashMap<String, ScheduledFuture<?>> result  = new ConcurrentHashMap<String, ScheduledFuture<?>>();
	public boolean putScheduledTask(Runnable task,int time,TimeUnit timeunit,String taskName){
		ScheduledFuture<?> value = scheduExec.schedule(task,time,timeunit);
		result.put(taskName, value);
		return result.containsKey(taskName);
	}

	private ScheduledExecutorUtil(){
		//定时清理result中已经执行完毕的定时任务
		scheduExec.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				if(result.size() > 0){
					for (String taskname : result.keySet()) {
						ScheduledFuture<?> task = result.get(taskname);
						if(task.isCancelled() || task.isDone()){
							result.remove(taskname);
						}
					}
				}

			}
		}, 1, 24*60, TimeUnit.MINUTES);
	}

	private boolean cancelScheduledTask(String taskName){
		if(!result.containsKey(taskName)){
			return true;
		}else{
			ScheduledFuture<?> task = result.get(taskName);
			if(task.isCancelled()){
				result.remove(taskName);
				return true;
			}
			if(task.isDone()){
				result.remove(taskName);
				throw new IllegalArgumentException(taskName + " have been cancelled !");
			}
			boolean isCancel =  task.cancel(true);
			if(isCancel){
				result.remove(taskName);
			}
			return isCancel;

		}
	}

	public void shutDownScheduedTaskPool(){
		scheduExec.shutdown();
	}

	public static void main(String[] args) {
		final long start = System.currentTimeMillis();
		ScheduledExecutorUtil test = new ScheduledExecutorUtil();
		test.putScheduledTask(new Runnable() {
			public void run() {
				System.out.println("timerOne,the time:" + (System.currentTimeMillis() - start));
				try {
					Thread.sleep(4000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, 20000, TimeUnit.MILLISECONDS,"test1");
		System.out.println(test.cancelScheduledTask("test1"));
		test.putScheduledTask(new Runnable() {
			public void run() {
				System.out.println("timerTwo,the time:" + (System.currentTimeMillis() - start));
			}
		}, 10000, TimeUnit.MILLISECONDS,"test2");
		System.out.println(test.cancelScheduledTask("test1"));
	}
}

Powered by andiHappy and Theme by AndiHappy