java中timer与thread,Java中Timer和ThreadPoolExecutor的区别和比较

今天闲来无事读Java中Timer的源码,发现Timer的注释中有这么一段

Java 5.0 introduced the {@code java.util.concurrent} package and

one of the concurrency utilities therein is the {@link

java.util.concurrent.ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor} which is a thread pool for repeatedly

executing tasks at a given rate or delay. It is effectively a more

versatile replacement for the {@code Timer}/{@code TimerTask}

combination, as it allows multiple service threads, accepts various

time units, and doesn’t require subclassing {@code TimerTask} (just

implement {@code Runnable}). Configuring {@code

ScheduledThreadPoolExecutor} with one thread makes it equivalent to

{@code Timer}.

其大意是说Timer的API有单线程的问题,一个定时器不允许同时执行任务。官方说在JDK1.5之后引入了ScheduledThreadPoolExecutor类来实现多线程的定时器。那就来看看到底是怎么回事把。

Timer

package com.freud.test;

import java.util.Date;

import java.util.Timer;

import java.util.TimerTask;

public class TimerTest {

private static long start = System.currentTimeMillis();

public static void main(String[] args) {

Timer timer = new Timer();

timer.scheduleAtFixedRate(new TimerTask() {

@Override

public void run() {

try {

System.out.println("Timer 1 start at:"

+ (System.currentTimeMillis() - start));

Thread.sleep(1000);

System.out.println("Timer 1 finish at:"

+ (System.currentTimeMillis() - start));

// throw new RuntimeException("Exception occured here!");

} catch (InterruptedException e) {

System.out.println("Thread was interrupted.");

}

}

}, new Date(), 1000);

timer.scheduleAtFixedRate(new TimerTask() {

@Override

public void run() {

try {

System.out.println("Timer 2 start at:"

+ (System.currentTimeMillis() - start));

Thread.sleep(1000);

System.out.println("Timer 2 finish at:"

+ (System.currentTimeMillis() - start));

} catch (InterruptedException e) {

System.out.println("Thread was interrupted.");

}

}

}, new Date(), 1000);

}

}

执行上述代码后会发现打印输出如下:

Timer 1 start at:1

Timer 1 finish at:1001

Timer 2 start at:1001

Timer 2 finish at:2001

Timer 2 start at:2001

Timer 2 finish at:3001

Timer 1 start at:3001

Timer 1 finish at:4001

Timer 1 start at:4001

Timer 1 finish at:5001

Timer 2 start at:5001

Timer 2 finish at:6002

Timer 2 start at:6002

Timer 2 finish at:7002

Timer 1 start at:7002

Timer 1 finish at:8002

Timer 1 start at:8002

Timer 1 finish at:9002

Timer 2 start at:9002

Timer 2 finish at:10002

Timer 2 start at:10002

Timer 2 finish at:11002

Timer 1 start at:11002

通过日志不难看出,在一个Timer中的2个TimerTask是有执行顺序的,也就是上一个没有执行完,下一个是不会触发的。而究其原因,看源码发现Timer的实现中只有一个TimerThread线程通过while (true)的loop来执行存储在TaskQueue中的定时器任务

public class Timer {

/**

* The timer task queue. This data structure is shared with the timer

* thread. The timer produces tasks, via its various schedule calls,

* and the timer thread consumes, executing timer tasks as appropriate,

* and removing them from the queue when they're obsolete.

*/

private final TaskQueue queue = new TaskQueue();

/**

* The timer thread.

*/

private final TimerThread thread = new TimerThread(queue);

并且在loop的过程中只捕获了InterruptedException导致其中一个Task出现错误,会影响接下来的所有Task的执行。

/**

* The main timer loop. (See class comment.)

*/

private void mainLoop() {

while (true) {

try {

//*****

if (taskFired) // Task fired; run it, holding no locks

task.run();

} catch(InterruptedException e) {

}

}

}

打开TimerTest中注释掉的throw new RuntimeException("Exception occured here!");代码,会发现Task2不会执行!

ScheduledThreadPoolExecutor

package com.freud.test;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExecutorTest {

private static long start = System.currentTimeMillis();

public static void main(String[] args) {

ScheduledExecutorService schedule = Executors.newScheduledThreadPool(1);

schedule.scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

try {

System.out.println("Schedule 1 start at:"

+ (System.currentTimeMillis() - start));

Thread.sleep(1000);

System.out.println("Schedule 1 finish at:"

+ (System.currentTimeMillis() - start));

// throw new RuntimeException("Exception occured here!");

} catch (InterruptedException e) {

System.out.println("Thread was interrupted.");

}

}

}, 1, 1, TimeUnit.SECONDS);

schedule.scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

try {

System.out.println("Schedule 2 start at:"

+ (System.currentTimeMillis() - start));

Thread.sleep(1000);

System.out.println("Schedule 2 finish at:"

+ (System.currentTimeMillis() - start));

} catch (InterruptedException e) {

System.out.println("Thread was interrupted.");

}

}

}, 1, 1, TimeUnit.SECONDS);

}

}

观察到的结果如下,可以发现是跟Timer的执行结果是一样的.

Schedule 1 start at:1003

Schedule 1 finish at:2004

Schedule 2 start at:2004

Schedule 2 finish at:3004

Schedule 1 start at:3004

Schedule 1 finish at:4004

Schedule 2 start at:4004

Schedule 2 finish at:5004

Schedule 1 start at:5004

Schedule 1 finish at:6004

Schedule 2 start at:6004

Schedule 2 finish at:7004

Schedule 1 start at:7004

此时,修改Executors.newScheduledThreadPool(1)为Executors.newScheduledThreadPool(2)创建两个线程来执行定时器任务,观察到结果预期应该是每秒钟2个任务同时执行,结果如下,符合预期。

Schedule 1 start at:1004

Schedule 2 start at:1004

Schedule 2 finish at:2005

Schedule 1 finish at:2005

Schedule 2 start at:2005

Schedule 1 start at:2005

Schedule 1 finish at:3005

Schedule 1 start at:3005

Schedule 2 finish at:3009

Schedule 2 start at:3009

Schedule 1 finish at:4005

Schedule 1 start at:4005

Schedule 2 finish at:4009

Schedule 2 start at:4009

当打开throw new RuntimeException("Exception occured here!");之后会发现Schedule2正常执行,Schedule1的异常不会影响Schedule2的执行!

Schedule 1 start at:1003

Schedule 2 start at:1004

Schedule 1 finish at:2004

Schedule 2 finish at:2004

Schedule 2 start at:2004

Schedule 2 finish at:3004

Schedule 2 start at:3004

Schedule 2 finish at:4004

Schedule 2 start at:4004

Schedule 2 finish at:5004

Schedule 2 start at:5004

Schedule 2 finish at:6004

Schedule 2 start at:6004

结论

Timer可以做的事情,通过ScheduledThreadPoolExecutor都可以做到,并且修复了其中Timer的部分设计上的缺陷。并且实现了多线程的执行,相对来说功能是比Timer强大了一个等级。

Java中Timer和ThreadPoolExecutor学习比较系列文章:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值