《Java并发编程实战》一书提到的用ExecutorService取代Java Timer有几个理由,我认为其中最重要的理由是:
如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以 TimerTask抛出的未检查的异常会终止timer线程。这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。此时,已经被安排但尚未执行的TimerTask永远不会再执行了,新的任务也不能被调度了。
stackoverflow上也有关于此问题的讨论:
http://stackoverflow.com/questions/409932/java-timer-vs-executorservice
Timer的问题:
package com.ljn.timer;
import java.util.Date;
import java.util.Timer;
/**
* @author lijinnan
* @date:2013-11-25 下午3:27:43
*/
public class TimerException {
public static void main(String[] args) {
System.out.println("start:" + new Date());
Timer timer = new Timer();
int delay = 1000;
int period = 2000;
timer.schedule(new OKTask(), delay * 2, period); //"OKTask" does not get chance to execute
timer.schedule(new ErrorTask(), delay, period); //exception in "ErrorTask" will terminate the Timer
}
/*输出:
start:Mon Nov 25 17:49:53 CST 2013
ErrorTask is executing...
error:Mon Nov 25 17:49:55 CST 2013
Exception in thread "Timer-0" java.lang.RuntimeException: something wrong
at com.ljn.timer.ErrorTask.run(ErrorTask.java:14)
*/
}
用ExecutorService则正常:
package com.ljn.timer;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author lijinnan
* @date:2013-11-25 下午3:35:39
*/
public class ScheduledExecutorServiceTest {
public static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
public static void main(String[] args){
System.out.println("start:" + new Date());
ErrorTask errorTask = new ErrorTask();
OKTask okTask = new OKTask();
int delay = 1000;
int period = 2000;
scheduledExecutorService.scheduleAtFixedRate(errorTask, delay, period, TimeUnit.MILLISECONDS); //"ErrorTask" throws Exception and then stopes.
scheduledExecutorService.scheduleAtFixedRate(okTask, delay * 2, period, TimeUnit.MILLISECONDS); //"OKTask" is executed periodically, not affected by "ErrorTask"
//scheduledExecutorService.shutdown();
}
/*
start:Mon Nov 25 17:54:22 CST 2013
ErrorTask is executing...
error occurs:Mon Nov 25 17:54:24 CST 2013
OKTask is executed:Mon Nov 25 17:54:24 CST 2013
OKTask is executed:Mon Nov 25 17:54:26 CST 2013
OKTask is executed:Mon Nov 25 17:54:28 CST 2013
......
*/
}
另外开发中常常会让任务在每天的指定时间点运行,示例如下:
package com.ljn.timer;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author lijinnan
* @date:2013-11-25 下午5:18:55
*/
public class FixedDatetimeTaskTest {
public static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
public static void main(String[] args) throws Exception {
System.out.println("start:" + new Date());
//每天的02:30:00执行任务
long delay = Helper.calcDelay(2, 30, 0);
long period = Helper.ONE_DAY;
scheduledExecutorService.scheduleAtFixedRate(new OKTask(), delay, period, TimeUnit.MILLISECONDS);
}
}
文章中用到的其他类:
package com.ljn.timer;
import java.util.Date;
import java.util.TimerTask;
public class ErrorTask extends TimerTask {
@Override
public void run() {
try {
System.out.println("ErrorTask is executing...");
Thread.sleep(1000);
System.out.println("error occurs:" + new Date());
throw new RuntimeException("something wrong");
} catch (InterruptedException e) {
}
}
}
package com.ljn.timer;
import java.util.Date;
import java.util.TimerTask;
public class OKTask extends TimerTask {
@Override
public void run() {
System.out.println("OKTask is executed:" + new Date());
}
}
package com.ljn.timer;
import org.joda.time.DateTime;
/**
* @author lijinnan
* @date:2013-11-25 下午5:17:40
*/
public class Helper {
private Helper() {}
public static final long ONE_DAY = 60 * 60 * 24;
public static long calcDelay(int hour, int minute, int second) {
if (!(0 <= hour && hour <=23 && 0 <= minute && minute <=59 && 0 <=second && second <= 59)) {
throw new IllegalArgumentException();
}
return calcDelay(fixed(hour, minute, second));
}
private static long calcDelay(DateTime targetDatetimeOfToday) {
long delay = 0;
DateTime now = new DateTime();
//时间点已过,只好延时到明天的这个时间点再执行
if (now.isAfter(targetDatetimeOfToday)) {
delay = now.plusDays(1).getMillis() - now.getMillis();
//时间点未到
} else {
delay = targetDatetimeOfToday.getMillis() - now.getMillis();
}
return delay;
}
/**
* 返回这样一个DateTime对象:
* 1.日期为今天
* 2.时分秒为参数指定的值
* @param hour 0-23
* @param minute 0-59
* @param second 0-59
* @return
*/
private static DateTime fixed(int hour, int minute, int second) {
return new DateTime()
.withHourOfDay(hour).withMinuteOfHour(minute).withSecondOfMinute(second);
}
}
分享到:
相关推荐
主要为大家详细介绍了java ExecutorService使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
使用Java的ExecutorService类创建了一个固定大小的线程池,并将任务安排到线程池中执行。 通过调用`scheduleTask()`方法,可以指定要执行的任务、延迟时间和延迟时间单位。 任务将在指定的延迟时间后被安排到线程池...
主要介绍了线程并发ScheduledExecutorService类,设置 ScheduledExecutorService ,2秒后,在 1 分钟内每 10 秒钟蜂鸣一次
NULL 博文链接:https://x125858805.iteye.com/blog/2191873
今天小编就为大家分享一篇关于在spring boot中使用java线程池ExecutorService的讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
其方法签名为executor(Runnable command),该方法接收一个Runable实例,它用来执行一个任务,任务即一个实现了Runnable接口的类,一般来说,Runnable任务开辟在新线程中的使用方法为:new Thread(new RunnableTask())...
接口 java.util.concurrent.ExecutorService 表述了异步执行的机制,并且可以让任务在后台执行。壹個 ExecutorService 实例因此特别像壹個线程池。事实上,在 java.util.concurrent 包中的 ExecutorService 的实现...
运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接
java超时取消正则表达式匹配方法,代码超时处理,设置代码执行时间,超棒的工具类 lambda,Callable,ExecutorService,超过执行5秒退出
使用 ExecutorService 多线程处理某个进程的简单示例。
主要介绍了java中Executor,ExecutorService,ThreadPoolExecutor详解的相关资料,需要的朋友可以参考下
主要介绍了Java使用ExecutorService来停止线程服务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
java8 源码 Java 并发多线程从简到全 参考: 目录: [TOC] 相关文档: kwseeker/netty Executors线程池.md 1 基本概念 1.1 CPU与线程的关系 1.2 线程与进程的区别和关系 1.3 吞吐量 1.4 线程安全 1.5 线程声明周期 ...
ExecutorService方法案例文件.zip
主要介绍了Java 线程池ExecutorService详解及实例代码的相关资料,线程池减少在创建和销毁线程上所花的时间以及系统资源的开销.如果不使用线程池,有可能造成系统创建大量线程而导致消耗系统内存以及”过度切换
ExecutorService的execute和submit方法
运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接.doc
Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 。Java可以编写桌面应用程序、Web应用...Callable是需要使用java.util.concurrent.ExecutorService.submit(Callable)方
共享资源同步 在进行多线程开发时最令人头痛的...import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /* * 这是一个生成器的抽象类 */ abstract class Generator { private b
从版本该库以多发行版JAR的形式提供,并且可以与Java 8作为类路径库或与Java 9+作为模块一起使用。 重要的! 在版本,工件已重命名:新名称: < dependency> < groupId>...