Java线程之Timer
简述
java.util.Timer是一个定时器,用来调度线程在某个时间执行。在初始化Timer时,开启一个线程循环提取TaskQueue任务数组中的任务,
如果任务数组为空,线程等待直到添加任务;
当添加任务时,唤醒线程,提取数组中标记为1的任务,
如果该任务状态为CANCELLED,则从数组中删除任务,继续循环提取任务
TimerTask
TimerTask是一个抽象类,它实现了Runnable接口,我们需要继承TimerTask来创建自己的任务类,然后可以使用Timer去调度我们自定义的任务类。
Timer是线程安全的,多个线程可以共享一个Timer对象不需要额外加锁。Timer使用java.util.TaskQueue 来存储添加的任务,在任何时间只有一个线程去执行TimerTask,例如,如果您正在创建一个计时器,每10秒运行一次,但是单线程执行需要20秒,计时器对象将继续向队列中添加任务,当一个线程完成后,它将通知队列,另一个线程将开始执行。
Timer对象使用Object对象的 wait 和 notify方法去调度TimerTask去执行的
事例
package com.lkf.mulithread;
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 {
//任务完成需要20秒
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);
//每个10秒调度一次
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();
}
}
}
定时器每隔10秒调度一次任务,一个任务执行时间需要20秒
输出结果:
TimerTask started
Timer task started at:Sun Mar 25 13:20:35 CST 2018
Timer task finished at:Sun Mar 25 13:20:55 CST 2018
Timer task started at:Sun Mar 25 13:20:55 CST 2018
Timer task finished at:Sun Mar 25 13:21:15 CST 2018
Timer task started at:Sun Mar 25 13:21:15 CST 2018
Timer task finished at:Sun Mar 25 13:21:35 CST 2018
Timer task started at:Sun Mar 25 13:21:35 CST 2018
Timer task finished at:Sun Mar 25 13:21:55 CST 2018
Timer task started at:Sun Mar 25 13:21:55 CST 2018
Timer task finished at:Sun Mar 25 13:22:15 CST 2018
Timer task started at:Sun Mar 25 13:22:15 CST 2018
TimerTask cancelled
Timer task finished at:Sun Mar 25 13:22:35 CST 2018
由输出结果可以确认,定时器将等待任务完成,一旦完成,它将再次从队列开始下一个任务
总结
Timer定时器可以作为守护线程对任务进行调度,计时器cancel()方法用于终止计时器并丢弃任何设置好的任务,但是,它不会干扰当前执行的任务,会让它完成。
当Timer定时器作为守护线程,一旦我们调用取消定时器方法,等所有正在执行的用户线程执行完毕,定时器线程将会被终止
定时器类包含多个schedule()方法,用于安排在给定日期或延迟之后运行一次任务,有几个scheduleAtFixedRate()方法在一定时间间隔内运行任务
当我们使用Timer作为定时任务调度器时,要确保调度时间间隔不大于任务运行时间,否则,任务队列大小将持续增长,最终任务将始终执行
另外当多线程并行处理定时任务时,Timer运行多个TimerTask时,只要其中一个任务抛出异常,那么所有的任务都将被终止
Java线程之Timer的更多相关文章
- Java线程之 InterruptedException 异常
Java线程之 InterruptedException 异常 当一个方法后面声明可能会抛出InterruptedException 异常时,说明该方法是可能会花一点时间,但是可以取消的方法. 抛 ...
- Java 多线程之Timer与ScheduledExecutorService
1.Timer管理延时任务的缺陷 a.以前在项目中也经常使用定时器,比如每隔一段时间清理项目中的一些垃圾文件,每个一段时间进行数据清洗:然而Timer是存在一些缺陷的,因为Timer在执行定时任务时只 ...
- 多线程之Timer和TimerTask
Timer是一种线程设施,用于安排以后在后台线程中执行的任务.可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask.TimerTask是一个抽象类,实现了Runnabl ...
- java 线程之executors线程池
一.线程池的作用 平时的业务中,如果要使用多线程,那么我们会在业务开始前创建线程,业务结束后,销毁线程.但是对于业务来说,线程的创建和销毁是与业务本身无关的,只关心线程所执行的任务.因此希望把尽可能多 ...
- java 线程之concurrent中的常用工具 CyclicBarrier
一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...
- C++/Java线程之分
JAVA线程状态图 1.C++/windows中主线程结束,其他线程必然死亡(即使调用pthread_detach解除父子关系,主线程消亡时也会导致子线程被迫关闭). ----1.1 一个进程中可以有 ...
- Java线程之CompletionService批处理任务
如果你向Executor提交了一个批处理任务,并且希望在它们完成后获得结果,怎么办呢? 为此你可以保存与每个任务相关联的Future,然后不断地调用 timeout为零的get,来检验Future是否 ...
- Java线程之Synchronized用法
synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对 ...
- Java线程之Java内存模型(jmm)
一.Java内存模型(jmm) 线程通信 消息传递 重排序 顺序一致性 Happens-Before As-If-Serial
随机推荐
- 23-Perl 面向对象
1.Perl 面向对象Perl 中有两种不同地面向对象编程的实现:一是基于匿名哈希表的方式,每个对象实例的实质就是一个指向匿名哈希表的引用.在这个匿名哈希表中,存储来所有的实例属性.二是基于数组的方式 ...
- java——ArrayList中常见方法用法
package com.xt.list; import java.util.ArrayList; import java.util.Iterator; import java.util.List; p ...
- 树莓派SD卡安装系统后扩容——实测简单高效
接上一篇博客安装了树莓派64位的系统,如果需要安装桌面等其他操作会面临文件系统分区空间紧张的局面,扩容方法如下: 在ubuntu上安装 gparted工具可以对SD卡重新分区 $sudo apt-ge ...
- C#面向对象10 继承
1.继承: **** 我们可能会在一些类中,写一些重复的成员.我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类. Student,Teacher,Driver ----子类 派生类 ...
- js变量声明提升
1.变量提升 根据javascript的运行机制和javascript没有块级作用域这个特点,可以得出,变量会声明提升移至作用域 scope (全局域或者当前函数作用域) 顶部的. 变量声明提升至全局 ...
- 关于jar冲突的解决方向servlet-api
1.可以考虑尽量往 java自带的jar 靠 比如说jdk-tools 2.如果用springboot项目 让其他jar 排除servlet-api的依赖 <dependency> ...
- Spring与junit4集成测试
一.应用场景:普通java web集成spring test, 项目结构:使用的是加入jar的方式,不是maven加入依赖的方式 注意:如果是引入jar包的方式,例如:spring-test4.0.5 ...
- oracle中行转列操作
数据准备阶段: CREATE TABLE CC (Student NVARCHAR2(2),Course NVARCHAR2(2),Score INT); INSERT into CC sele ...
- aipai服务架构
概述 业务服务器30+ 1.根据业务不同,有四个主入口,负责负载均衡. 2.主要是业务分离,防止宕机影响所有业务. 3.nginx反向代理,保证每个业务至少有两个服务. redis集群12台 主要使用 ...
- 【wifi移植 1】 ap6210 wifi模块移植
1. 编译wifi相关功能为模块,生成bcmdhd.ko:由bcmdhd.ko的模块信息可知,该模块依赖于cfg80211.ko和rfkill.ko. 2. 写脚本,开机自动加载wifi模块. 3. ...