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类通过对象的waitnotify方法来调度任务。

参见如下代码:

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的更多相关文章

  1. Java线程和多线程(十二)——线程池基础

    Java 线程池管理多个工作线程,其中包含了一个队列,包含着所有等待被执行的任务.开发者可以通过使用ThreadPoolExecutor来在Java中创建线程池. 线程池是Java中多线程的一个重要概 ...

  2. Java线程与多线程教程

    本文由 ImportNew - liken 翻译自 Journaldev.   Java线程是执行某些任务的轻量级进程.Java通过Thread类提供多线程支持,应用可以创建并发执行的多个线程. 应用 ...

  3. Java线程和多线程(十三)——Callable,Future,FutureTask

    在Java多线程之中,Callable和Future的使用时非常广泛的.在之前的文章中,我们了解了关于Java线程池基础的一些内容,知道如何提交Runnable的任务.但是,Runnable的任务是无 ...

  4. Java线程和多线程(三)——线程安全和同步

    线程安全在Java中是一个很重要的课题.Java提供的多线程环境支持使用Java线程.我们都知道多线程共享一些对象实例的话,可能会在读取和更新共享数据的事后产生数据不一致问题. 线程安全 之所以会产生 ...

  5. Java线程和多线程(一)——线程的基本概念

    Java 线程是一个轻量级执行任务的处理单元.Java提供了Thread类来支持多线程,开发者在应用中可以创建多个线程来支持并发执行任务. 在应用中存在两种类型的线程,用户线程和守护线程.当我们启动应 ...

  6. Java 线程与多线程

    Java是一门支持多线程的编程语言! 什么是进程? 计算机中内存.处理器.IO等资源操作都要为进程进行服务. 一个进程上可以创建多个线程,线程比进程更快的处理单元,而且所占用的资源也小,多线程的应用也 ...

  7. Java线程和多线程(八)——Thread Dump

    Java的Thread Dump就是列出JVM中所有激活状态的线程. Java Thread Dump Java Thread Dump在分析应用性能瓶颈和死锁的时候,是非常有效的. 下面将介绍多种不 ...

  8. Java线程和多线程(十五)——线程的活性

    当开发者在应用中使用了并发来提升性能的同时,开发者也需要注意线程之间有可能会相互阻塞.当整个应用执行的速度比预期要慢的时候,也就是应用没有按照预期的执行时间执行完毕.在本章中,我们来需要仔细分析可能会 ...

  9. Java线程和多线程(十四)——Synchronized关键字解析

    曾经有一个比较有趣的面试问题,那就是,关于使用synchronized关键字,是用在方法上面尾号,还是用在一个代码块上面为好? 答案就是使用锁定代码块为更好.因为这样不会锁定对象.当synchroni ...

随机推荐

  1. 《3D打印:从想象到现实》:基本没发现独到之处

    本书汇总了3D打印的相关咨询:原理.可能的或已经实现的应用.商业模式等等.由于3D打印是最近媒体上比较热的信息,对我来说书中的大部分内容都没有独到之处,都是已知的.

  2. Android获取手机安装的浏览器列表

    最近碰到一个同事询问如何查询本地安装的浏览器列表,其使用的代码如下: public static List<ResolveInfo> getBrowserList(Context cont ...

  3. datatable 动态显示/隐藏列

    这个例子演示了 column().visible()方法来隐藏显示列,通过点击列按钮动态切换 <table id="example" class="display& ...

  4. Object c的NSString的使用,创建,拼接和分隔,子string,substring

    main: // //  main.m //  StringDemo // //  Created by 千 on 16/9/22. //  Copyright © 2016年 kodulf. All ...

  5. (第七场)A Minimum Cost Perfect Matching 【位运算】

    题目链接:https://www.nowcoder.com/acm/contest/145/A A.Minimum Cost Perfect Matching You have a complete ...

  6. C# 动态改变webservice的访问地址

    1.添加一个App.config配置文件. 2.配置服务http://Lenovo-PC:80/EvisaWS/WharfService?wsdl,那么在上面的文件中就会自动生成服务的配置: < ...

  7. HDU 1254 推箱子(BFS加优先队列)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1254 推箱子 Time Limit: 2000/1000 MS (Java/Others)    Me ...

  8. WebClient设置Expect: 100-continue

    今天使用WebClient进行post发送数据的时候.总是无响应.实在没办法了.只好用fiddler抓包看一看.自己构造请求看哪里有问题. 发现请求头加上这句话后就无响应了.Expect: 100-c ...

  9. caffe convert mxnet

    https://github.com/apache/incubator-mxnet/tree/430ea7bfbbda67d993996d81c7fd44d3a20ef846/tools/caffe_ ...

  10. 使用transfor让图片旋转

    材料:Transform,onmouseout,onmouseover css: html: js: