四、Timer解析
Timer的基本使用流程
- 第一件事:new一个timer(计时器)
- 第二件事:定义一个任务TimerTask类【这里起名字为FooTimerTask】
- 包装一个定时任务:任务写在下面的一个类FooTimerTask(这个类需要继承TimerTask)
- 这个TimerTask实现了Runable接口(所以需要自己实现run()方法)。
- 在run()方法里写业务逻辑
- 模拟延时时间
- 定义一个变量
- 通过构造器来传入自己定义的日志名字
- Timer就两件事,然后就是启动项目了
- new一个对象
- 然后即使启动任务的方法
- schedule()
- scheduleAtFixedRate()
// 预设的执行时间nextExecutTime 12:00:00 12:00:02 12:00:04
//schedule 真正的执行时间 取决上一个任务的结束时间 ExecutTime 03 05 08 丢任务(少执行了次数)
//scheduleAtFixedRate 严格按照预设时间 12:00:00 12:00:02 12:00:04(执行时间会乱)
//单线程 任务阻塞 任务超时
- 1
- 2
- 3
- 4
Timer基本使用的缺点
- 该方法的缺点,不管你放多少任务,都是以单线程来运行的(源码里写的)。
- 单线程就会导致——任务阻塞,任务超时
解决单线程导致的任务阻塞,超时的方法:【正确的用法】
- 在TimerTask中的run()方法里面另起线程池【自己写】执行(这样就可以避免了)
使用场景:
- 必须是固定的时间,要不就是相对的时间。
- 每个月的一号执行就会做不到【严重依赖系统时间】。
代码展示:
- 需要使用就需要自己另起线程池,启动多线程
package com.tuling.timer;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer t = new Timer();//任务启动
for (int i=0; i<2; i++){
TimerTask task = new FooTimerTask("foo"+i);
t.scheduleAtFixedRate(task,new Date(),2000);//任务添加 10s 5次 4 3
// 预设的执行时间nextExecutTime 12:00:00 12:00:02 12:00:04
//schedule 真正的执行时间 取决上一个任务的结束时间 ExecutTime 03 05 08 丢任务(少执行了次数)
//scheduleAtFixedRate 严格按照预设时间 12:00:00 12:00:02 12:00:04(执行时间会乱)
//单线程 任务阻塞 任务超时
}
}
}
class FooTimerTask extends TimerTask {
private String name;
public FooTimerTask(String name) {
this.name = name;
}
public void run() {
try {
System.out.println("name="+name+",startTime="+new Date());
Thread.sleep(3000);
System.out.println("name="+name+",endTime="+new Date());
//线程池执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
问题补充图:应用,任务调度,问题