Java线程和多线程——TimerTask
Posted EthanPark
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java线程和多线程——TimerTask相关的知识,希望对你有一定的参考价值。
Java中的java.util.Timer
是一个工具类,可以用于调度一个线程在将来的某一个时刻执行特定的任务。Java Timer类可以将一个任务定时执行一次,或者是以后以每隔一定的时间间隔来触发一次。
Java TimerTask
java.util.TimerTask
是一个抽象类,也同时实现了Runnable
接口的。我们可以继承这个类来创建我们自己的TimerTask
之后由Timer
来调度。
Java Timer举例
Java Timer类是线程安全的,多个线程可以共享一个Timer对象而不需要额外的同步操作。Timer类会使用java.util.TaskQueue
来将Task以一定的时间间隔加入到队列之中,而且,在任何时候仅仅能有一个线程在运行TimerTask。举例来说,开发者创建了一个Timer每隔10秒来执行一次,但是单线程的执行需要使用20秒,那么Timer对象会持续将任务添加到队列中,只要线程的执行完成了,它会通知队列中另一个线程来立刻执行。
Java Timer类通过对象的wait
和notify
方法来调度任务。
参见如下代码:
package com.sapphire.threads;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask
@Override
public void run()
System.out.println("Timer task started at:"+new Date());
completeTask();
System.out.println("Timer task finished at:"+new Date());
private void completeTask()
try
//assuming it takes 20 secs to complete the task
Thread.sleep(20000);
catch (InterruptedException e)
e.printStackTrace();
public static void main(String args[])
TimerTask timerTask = new MyTimerTask();
//running timer task as daemon thread
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(timerTask, 0, 10*1000);
System.out.println("TimerTask started");
//cancel after sometime
try
Thread.sleep(120000);
catch (InterruptedException e)
e.printStackTrace();
timer.cancel();
System.out.println("TimerTask cancelled");
try
Thread.sleep(30000);
catch (InterruptedException e)
e.printStackTrace();
需要注意的是,上面的一个线程的执行会花掉20秒,但是Java的Timer对象调度的执行间隔是10秒执行一次,所以输出如下:
TimerTask started
Timer task started at:Fri Oct 14 12:59:27 CST 2016
Timer task finished at:Fri Oct 14 12:59:47 CST 2016
Timer task started at:Fri Oct 14 12:59:47 CST 2016
Timer task finished at:Fri Oct 14 13:00:07 CST 2016
Timer task started at:Fri Oct 14 13:00:07 CST 2016
Timer task finished at:Fri Oct 14 13:00:27 CST 2016
Timer task started at:Fri Oct 14 13:00:27 CST 2016
Timer task finished at:Fri Oct 14 13:00:47 CST 2016
Timer task started at:Fri Oct 14 13:00:47 CST 2016
Timer task finished at:Fri Oct 14 13:01:07 CST 2016
Timer task started at:Fri Oct 14 13:01:07 CST 2016
TimerTask cancelled
Timer task finished at:Fri Oct 14 13:01:27 CST 2016
输出也确认了一点,就是如果一个任务已经开始执行了,那么Timer会等待它的完成,而一旦完成,Timer会立刻开始执行队列中的下一个任务。
Java的对象可以以守护线程的方式来调度相关的任务。Timer的cancel()
方法是用来结束Timer并抛弃其他的调度任务的。然而,这个方法不会影响现在正在执行的任务,而是让其继续运行下去。如果我们将Timer的运行配置为守护线程,那么无论我们是否调用cancel()
方法,一旦用户线程完成执行,Timer都会立刻结束掉。
Timer类中包含多个schedule()
方法,可以调度任务在指定时间执行一次,或者在一些延迟后来执行。Timer类中也包含了一些scheduleAtFixedRate()
方法来以指定的时间间隔来运行一些任务。
注意:当使用Timer来进行任务调度的时候,开发者需要确认无时间间隔一定要大于线程的执行时间。否则,任务的队列会变得越来越长而实际的任务也会总是在执行。
前面的描述也相当于隐含着提到了Timer的可能的错误行为,那就是Timer执行任务的方式。Timer的实现是内部包含一个队列,和一个线程,然后来定时将任务添加到执行队列之中的。
public class Timer private final TaskQueue queue = new TaskQueue(); private final TimerThread thread = new TimerThread(queue);
这样就可能出现问题,如果将2个
TimerTask
加入到Timer中进行执行,如果其中一个Timer执行的比较忙,而另一个需要执行的又比较快,可能就会出现问题。举例来说,两个任务,一个每隔300秒执行一次,一个每隔5秒执行一次,如果第一个任务执行了20秒才结束,那么因为上面实现的原因,会将第二个任务阻塞20秒,而一口气执行四次。所以开发者在使用Timer
来进行任务调度的时候,需要考虑性能以及可能出现的错误行为。
以上是关于Java线程和多线程——TimerTask的主要内容,如果未能解决你的问题,请参考以下文章