JAVA定时任务TimerTimerTask笔记
gs什么意思
JAVA定时任务 Timer TimerTask 笔记
前⾔
我并不喜欢⼲什么都动不动弄⼀⼤坨框架, ⾸先还是该掌握好⾃带的基础⼯具 , 然后是spring , 然后才是更⼤坨的⼯具Java最基本的定时任务 : new⼀个线程并指定间隔和结束条件
public static boolean是否循环=true;
public static long间隔时间毫秒=3000;
public static void⼲点什么⽅法(){ System.out.println("世界你好");}
public static void arguments){
new Thread(()->{
while(是否循环){
⼲点什么⽅法();
try{ Thread.sleep(间隔时间毫秒);}catch(Exception e){println("sleep能有什么错");}
}
}).start();
}
Timer + TimerTask 简单⽤法说明
例⼦:
1. 实现 TimerTask的run⽅法, 明确要做什么
可以继承实现, 也可⽤匿名内部类
2. new ⼀个Timer
3. 调⽤Timer实例的 schedule 或 scheduleAtFixedRate ⽅法
将TimerTask放⼊Timer,并指定开始时间 和 间隔时间
延时三秒后执⾏⼀次:
long三秒后=3000;
Timer timer =new Timer();
timer.schedule(new TimerTask(){
@Override
public void run(){
System.out.println("要执⾏的代码");
timer.cancel();
}
chicago},三秒后);
延时三秒后, 每秒执⾏⼀次, ⽤scheduleAtFixedRate⽅法:
long三秒后=3000,间隔1秒=1000;
Timer timer =new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
@Override
public void run(){
System.out.println("要执⾏的代码");
}
},三秒后,间隔1秒);
延时三秒后, 每秒执⾏⼀次, ⽤schedule⽅法:
long三秒后=3000,间隔1秒=1000;
Timer timer =new Timer();
timer.schedule(new TimerTask(){
@Override
public void run(){
ever sinceSystem.out.println("要执⾏的代码");
try{Thread.sleep(500);}catch(Exception e){}//不会多加500毫秒
}
},三秒后,间隔1秒);
java.util.Timer
基本原理
创建了⼀个任务队列 , 创建了⼀个执⾏线程
来⾃openJDK15的源码:
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);
Timer会创建⼀个线程执⾏TaskQueue中的TimerTask
⼀个Timer⼀个线程 , 所以 , 如果想多个不相⼲的任务互不⼲扰,就多new⼏个Timer,分别放⼊相⼲的任务可以放⼊同⼀个Timer
va怎么读主要⽅法
构造⽅法
public Timer()
public Timer(boolean isDaemon)
public Timer(String name)
public Timer(String name, boolean isDaemon)
Timer()
public Timer(){
this("Timer-"+rialNumber());
jobtitle}
Timer(String name)
public Timer(String name){
thread.tName(name);
thread.start();
}
Timer(boolean isDaemon)
public Timer(boolean isDaemon){
this("Timer-"+rialNumber(), isDaemon);
}
Timer(String name, boolean isDaemon)
public Timer(String name,boolean isDaemon){
thread.tName(name);hack
thread.tDaemon(isDaemon);
thread.start();
}
构造⽅法的 isDaemon 参数
isDaemon 表⽰ 是否是守护线程 , 默认设置参考 Thread类
/* Whether or not the thread is a daemon thread. */
private boolean daemon =fal;
不指定的话, 默认fal 不是守护线程
守护线程和默认线程的区别
守护线程更像是跟班 , 主线程退出,就跟着退出了. 所以, 守护timer可能什么也没做程序就完了
默认线程会⼀直等到⾃⾝执⾏完, 或⼀直在循环中, 所以, 默认timer排程后, 即便⾃⼰已执⾏完, 主线程也早执⾏完了, 但timer的线程依旧不会退出
schedule 和 scheduleAtFixedRate
schedule
public void schedule(TimerTask task, long delay) //延时执⾏⼀次
public void schedule(TimerTask task, Date time) //延时执⾏⼀次
public void schedule(TimerTask task, long delay, long period) //延时且循环
public void schedule(TimerTask task, Date firstTime, long period) //延时且循环
scheduleAtFixedRate
public void scheduleAtFixedRate(TimerTask task, long delay, long period) //延时且循环
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) //延时且循环
⽐较 schedule⽅法和 scheduleAtFixedRate⽅法的区别
schedule(TimerTask task, long delay, long period) openJDK15
public void schedule(TimerTask task,long delay,long period){
if(delay <0)
throw new IllegalArgumentException("Negative delay.");
if(period <=0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay,-period);
}
scheduleAtFixedRate(TimerTask task, long delay, long period) openJDK15
public void scheduleAtFixedRate(TimerTask task,long delay,long period){
if(delay <0)
throw new IllegalArgumentException("Negative delay.");
if(period <=0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, period);
}
它们都调⽤sched⽅法
不同在于, 传⼊的 period ⼀个为负 , ⼀个为正
private void sched(TimerTask task, long time, long period)
/**
* Schedule the specified timer task for execution at the specified
* time with the specified period, in milliconds. If period is
* positive, the task is scheduled for repeated execution; if period is
* zero, the task is scheduled for one-time execution. Time is specified
* Time() format. This method checks timer state, task state,
* and initial execution time, but not period.英文双引号
*
Schedule(排程)指定的timerTask以指定的时间在指定的period(以毫秒为单位)执⾏。
如果period为正,则计划将任务安排为重复执⾏;
如果period为零,则task只执⾏⼀次。
时间以Time()格式指定。
此⽅法检查timer状态,task状态和初始执⾏时间,但不检查period(周期)。
*/
private void sched(TimerTask task,long time,long period){
if(time <0)
throw new IllegalArgumentException("Illegal execution time.");
// Constrain value of period sufficiently to prevent numeric
// overflow while still being effectively infinitely large.
if(Math.abs(period)>(Long.MAX_VALUE >>1))
period >>=1;
synchronized(queue){
if(!wTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock){
if(task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.period = period;
task.state = TimerTask.SCHEDULED;bent
}
queue.add(task);
Min()== task)
}
}
sched源码 仍然看不出它们的区别, 但可以知道每个task都有period属性, 在sched中被传⼊ " task.period = period; "
继续查找, 终于找到⼲循环⼯作的主⽅法
class TimerThread类 的 private void mainLoop()
TimerThread类 的 private void mainLoop()
/**
* The main timer loop. (See class comment.)
*/
private void mainLoop(){
while(true){
try{
TimerTask task;
boolean taskFired;
synchronized(queue){
// Wait for queue to become non-empty
while(queue.isEmpty()&& newTasksMayBeScheduled)
queue.wait();
if(queue.isEmpty())
break;// Queue is empty and will forever remain; die
// Queue nonempty; look at first evt and do the right thing
long currentTime, executionTime;
task = Min();
synchronized(task.lock){
宿迁中考查分if(task.state == TimerTask.CANCELLED){
continue;// No action required, poll queue again
}
currentTime = System.currentTimeMillis();
executionTime = ExecutionTime;
if(taskFired =(executionTime<=currentTime)){
if(task.period ==0){// Non-repeating, remove
task.state = TimerTask.EXECUTED;
}el{// Repeating task, reschedule
task.period<0? currentTime - task.period
: executionTime + task.period);
}
}
}
if(!taskFired)// Task hasn't yet fired; wait
queue.wait(executionTime - currentTime);
}
if(taskFired)// Task fired; run it, holding no locks
task.run();
}catch(InterruptedException e){
}
}
}
可以看到这句
task.period<0? currentTime - task.period
: executionTime + task.period);
和这句
queue.wait(executionTime - currentTime);//暂停(执⾏时间减去当前时间)