全面了解Java Timer定時(shí)器類
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
Timer類介紹
Timer類的主要作用是設(shè)置計(jì)劃任務(wù),即在指定時(shí)間開(kāi)始執(zhí)行某一個(gè)任務(wù)。Timer主要方法如圖:

schedule(TimerTask task, Date time)方法測(cè)試
該方法的作用是在指定日期執(zhí)行一次某一任務(wù)。
TimerTask類:
import java.util.TimerTask;
public class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("任務(wù)開(kāi)始了,執(zhí)行時(shí)間為:"+System.currentTimeMillis());
}
}
測(cè)試類
import java.util.Date;
import java.util.Timer;
public class testTimer {
public static void main(String[] args) throws InterruptedException{
Long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)期時(shí)間為"+nowTime);
long scheduleTime=nowTime+10000;
System.out.println("開(kāi)始執(zhí)行時(shí)間:"+scheduleTime);
MyTask myTask = new MyTask();
Timer timer = new Timer();
Thread.sleep(1000);
timer.schedule(myTask,new Date(scheduleTime));
Thread.sleep(Integer.MAX_VALUE);
}
}

10秒之后任務(wù)執(zhí)行完了,但是進(jìn)程還沒(méi)有銷毀,還在呈紅色按鈕。說(shuō)明內(nèi)部還有線程在執(zhí)行。為什么會(huì)出現(xiàn)這種情況?
查看Timer類的源碼可以知道是因?yàn)樵趧?chuàng)建Timer對(duì)象時(shí)啟動(dòng)了一個(gè)新的進(jìn)程。
private final TimerThread thread = new TimerThread(queue);
public Timer(String name) {
thread.setName(name);
thread.start();
}
TimerThread 是線程類,但是并不是一個(gè)守護(hù)線程,而且還一直在運(yùn)行,一直在運(yùn)行的原因是線程內(nèi)部有一個(gè)死循環(huán),mainLoop()方法,其源碼如下:
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 = queue.getMin();
synchronized(task.lock) {
if (task.state == TimerTask.CANCELLED) {
queue.removeMin();
continue; // No action required, poll queue again
}
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime<=currentTime)) {
if (task.period == 0) { // Non-repeating, remove
queue.removeMin();
task.state = TimerTask.EXECUTED;
} else { // Repeating task, reschedule
queue.rescheduleMin(
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) {
}
}
private void mainLoop() 方法內(nèi)部使用while死循環(huán)一直執(zhí)行計(jì)劃任務(wù),并不退出循環(huán),但是根據(jù)源碼的執(zhí)行流程,退出循環(huán)的核心代碼如下:
while (queue.isEmpty() && newTasksMayBeScheduled)
queue.wait();
if (queue.isEmpty())
break; // Queue is empty and will forever remain; die
下面我們來(lái)簡(jiǎn)單分析一下源代碼
1)使用while循環(huán)對(duì)queue.isEmpty()&&newTasksMayBeScheduled條件進(jìn)行判斷。
2)當(dāng)&&兩端運(yùn)算結(jié)果都為true時(shí),執(zhí)行wait()方法使當(dāng)前線程暫停運(yùn)行,等待被喚醒。
3)喚醒線程的時(shí)機(jī)是執(zhí)行了public void schedule(TimerTask task, Date time)方法。
4)喚醒線程后while繼續(xù)判斷queue.isEmpty()&&newTasksMayBeScheduled條件。如果queue.isEmpty()結(jié)果為true,則說(shuō)明隊(duì)列里并沒(méi)有任務(wù)執(zhí)行,而且boolean newTasksMayBeScheduled的值由true變成false,繼續(xù)執(zhí)行下面的if語(yǔ)句。
5)if (queue.isEmpty())中的結(jié)果為true,說(shuō)明隊(duì)列為空,那么就執(zhí)行break語(yǔ)句退出while()死循環(huán)。
6)執(zhí)行public void cancel(),則會(huì)使boolean變量newTasksMayBeScheduled的值有true變成false。
7)不執(zhí)行public void cancel()方法,則變量newTasksMayBeScheduled的值就不會(huì)是false,進(jìn)程就會(huì)一直呈死循環(huán)的狀態(tài),進(jìn)程不銷毀的原因就是因?yàn)檫@個(gè)。cancel()方法源代碼如下
public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}
使用cancel方法來(lái)銷毀線程
Timer類中的cancel方法作用就是終止此計(jì)時(shí)器,當(dāng)前安排的一切任務(wù)都不會(huì)執(zhí)行。不過(guò)這并不會(huì)干擾當(dāng)前正在執(zhí)行的任務(wù)(如果存在當(dāng)前任務(wù))。一旦終止了計(jì)時(shí)器,那么他執(zhí)行的線程也會(huì)終止,并且無(wú)法根據(jù)他安排更多的任務(wù)。
根據(jù)上面的源代碼分析可知,當(dāng)隊(duì)列為空,并且newTasksMayBeScheduled的值是false時(shí)退出死循環(huán),導(dǎo)致TimerThread線程結(jié)束運(yùn)行并且銷毀。
創(chuàng)建Test2類代碼如下:
public class Test2 {
public static void main(String[] args) throws InterruptedException{
Long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)期時(shí)間為"+nowTime);
long scheduleTime=nowTime+15000;
System.out.println("開(kāi)始執(zhí)行時(shí)間:"+scheduleTime);
MyTask myTask = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,new Date(scheduleTime));
Thread.sleep(18000);
timer.cancel();
}
}

可見(jiàn)全部線程已經(jīng)銷毀了。
schedule(TimerTask task, Date time)方法的幾種情況測(cè)試
計(jì)劃早于當(dāng)前時(shí)間—立即執(zhí)行當(dāng)前任務(wù)
mytask類
public class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("任務(wù)執(zhí)行了,時(shí)間為:"+System.currentTimeMillis());
}
}
//計(jì)劃早于當(dāng)前時(shí)間---立即執(zhí)行當(dāng)前任務(wù)
public class Test1 {
public static void main(String[] args) {
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
long scheduleTime=(nowTime-5000);
System.out.println("計(jì)劃時(shí)間為:"+scheduleTime);
MyTask myTask = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,new Date(scheduleTime));
}
}
結(jié)果:
當(dāng)前時(shí)間:1616912643987
計(jì)劃時(shí)間為:1616912638987
任務(wù)執(zhí)行了,時(shí)間為:1616912643987
schedule方法可以執(zhí)行多個(gè)任務(wù)
//執(zhí)行多個(gè)任務(wù)
public class Test2 {
public static void main(String[] args){
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
long scheduleTime=(nowTime+5000);
long scheduleTime2=(nowTime+8000);
System.out.println("計(jì)劃時(shí)間為:"+scheduleTime);
System.out.println("計(jì)劃時(shí)間為:"+scheduleTime2);
MyTask myTask = new MyTask();
MyTask myTask2 = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,new Date(scheduleTime));
timer.schedule(myTask2,new Date(scheduleTime2));
}
}
結(jié)果:
當(dāng)前時(shí)間:1616912808406
計(jì)劃時(shí)間為:1616912813406
計(jì)劃時(shí)間為:1616912816406
任務(wù)執(zhí)行了,時(shí)間為:1616912813417
任務(wù)執(zhí)行了,時(shí)間為:1616912816407
延時(shí)執(zhí)行TimerTask
TimerTask以隊(duì)列的方式逐一按順序執(zhí)行,所以執(zhí)行的時(shí)間可能與預(yù)期時(shí)間并不一致,因?yàn)榍懊嫒蝿?wù)可能消耗的時(shí)間較長(zhǎng),后面的任務(wù)運(yùn)行時(shí)間可能被延后。
public class MyTaskA extends TimerTask {
@Override
public void run() {
try {
System.out.println("A begin time=" + System.currentTimeMillis());
Thread.sleep(10000);
System.out.println("A end time=" + System.currentTimeMillis());
}catch (Exception e){
e.printStackTrace();
}
}
}
public class MyTaskB extends TimerTask {
@Override
public void run() {
try {
System.out.println("B begin time=" + System.currentTimeMillis());
Thread.sleep(10000);
System.out.println("B end time=" + System.currentTimeMillis());
}catch (Exception e){
e.printStackTrace();
}
}
}
測(cè)試類:
public class Test3 {
public static void main(String[] args) {
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
long scheduleTime=nowTime;
long scheduleTime2=(nowTime+5000);
System.out.println("計(jì)劃時(shí)間為:"+scheduleTime);
System.out.println("計(jì)劃時(shí)間為:"+scheduleTime2);
MyTaskA myTaskA = new MyTaskA();
MyTaskB myTaskB = new MyTaskB();
Timer timer = new Timer();
timer.schedule(myTaskA,new Date(scheduleTime));
timer.schedule(myTaskB,new Date(scheduleTime2));
}
}
結(jié)果:
當(dāng)前時(shí)間:1616913423195
計(jì)劃時(shí)間為:1616913423195
計(jì)劃時(shí)間為:1616913428195
A begin time=1616913423195
A end time=1616913433196
B begin time=1616913433196
B end time=1616913443211
計(jì)劃B原本執(zhí)行的時(shí)間是long scheduleTime2=(nowTime+5000);與計(jì)劃A運(yùn)行間隔時(shí)間為5秒,但是因?yàn)锳任務(wù)運(yùn)行需要10秒,所有任務(wù)A執(zhí)行結(jié)束的時(shí)間就是任務(wù)B開(kāi)始的時(shí)間。
schedule(TimerTask task, Date firstTime, long period)方法測(cè)試
計(jì)劃時(shí)間晚于當(dāng)前時(shí)間————在未來(lái)執(zhí)行的效果
該方法的作用是在指定日期之后按照指定的時(shí)間間隔無(wú)限的執(zhí)行某一個(gè)任務(wù)。
public class Test3 {
public static void main(String[] args) {
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
long scheduleTime=(nowTime+10000);
System.out.println("計(jì)劃時(shí)間為:"+scheduleTime);
MyTask myTask = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,new Date(scheduleTime),4000);
}
}
結(jié)果:
計(jì)劃時(shí)間為:1616914137464
任務(wù)執(zhí)行了,時(shí)間為:1616914137474
任務(wù)執(zhí)行了,時(shí)間為:1616914141494
任務(wù)執(zhí)行了,時(shí)間為:1616914145514
任務(wù)執(zhí)行了,時(shí)間為:1616914149534
從程序的運(yùn)行結(jié)果來(lái)看每隔4秒運(yùn)行一次,并且無(wú)限重復(fù)的執(zhí)行該任務(wù)。
計(jì)劃時(shí)間早于當(dāng)前時(shí)間————立即執(zhí)行的效果
public class Test3 {
public static void main(String[] args) {
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
long scheduleTime=(nowTime-10000);
System.out.println("計(jì)劃時(shí)間為:"+scheduleTime);
MyTask myTask = new MyTask();
Timer timer = new Timer();
timer.schedule(myTask,new Date(scheduleTime),4000);
}
}
結(jié)果:
當(dāng)前時(shí)間:1616914545243
計(jì)劃時(shí)間為:1616914535243
任務(wù)執(zhí)行了,時(shí)間為:1616914545243
任務(wù)執(zhí)行了,時(shí)間為:1616914549253
任務(wù)執(zhí)行了,時(shí)間為:1616914553254
任務(wù)執(zhí)行了,時(shí)間為:1616914557264
任務(wù)執(zhí)行了,時(shí)間為:1616914561283
延時(shí)執(zhí)行TimerTask任務(wù)
public class Test3 {
public static void main(String[] args) {
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
long scheduleTime=nowTime;
System.out.println("計(jì)劃時(shí)間為:"+scheduleTime);
MyTaskA myTaskA = new MyTaskA();
Timer timer = new Timer();
timer.schedule(myTaskA,new Date(scheduleTime),4000);
}
}
結(jié)果:
當(dāng)前時(shí)間:1616914846353
計(jì)劃時(shí)間為:1616914846353
A begin time=1616914846353
A end time=1616914851363
A begin time=1616914851363
A end time=1616914856373
A begin time=1616914856373
A end time=1616914861383
代碼schedule(myTaskA,new Date(scheduleTime),4000);本來(lái)計(jì)劃每個(gè)任務(wù)執(zhí)行時(shí)間為4秒但是任務(wù)A執(zhí)行了Thread.sleep(5000)要5秒。
TimerTask類中的cancel()方法和Timer中的cancel()方法的區(qū)別
TimerTask類中的cancel()方法
TimerTask類中的cancel()方法作用是將自己在任務(wù)隊(duì)列中清除。該方法的源代碼如下
public boolean cancel() {
synchronized(lock) {
boolean result = (state == SCHEDULED);
state = CANCELLED;
return result;
}
}
從方法的源代碼可以分析出執(zhí)行TimerTask中的該方法,當(dāng)前任務(wù)TimerTask任務(wù)的state狀態(tài)將會(huì)變成CANCELLED。
public class MyThreadA extends TimerTask {
@Override
public void run() {
System.out.println("A run time="+System.currentTimeMillis());
this.cancel();
System.out.println("A任務(wù)將自己移除");
}
}
class MyThreadB extends TimerTask{
@Override
public void run() {
System.out.println("B run time="+System.currentTimeMillis());
}
}
class test{
public static void main(String[] args) {
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
System.out.println("計(jì)劃時(shí)間為:"+nowTime);
MyThreadB myThreadB = new MyThreadB();
MyThreadA myThreadA = new MyThreadA();
Timer timer = new Timer();
timer.schedule(myThreadA,new Date(nowTime),3000);
timer.schedule(myThreadB,new Date(nowTime),3000);
}
結(jié)果:
當(dāng)前時(shí)間:1616916022030
計(jì)劃時(shí)間為:1616916022030
A run time=1616916022035
A任務(wù)將自己移除
B run time=1616916022035
B run time=1616916025041
B run time=1616916028061
Timer類中的cancel()方法
Timer類中的cancel()方法作用是將任務(wù)隊(duì)列中所有任務(wù)清除。該方法的源代碼如下
public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}
public class MyThreadA extends TimerTask {
@Override
public void run() {
System.out.println("A run time="+System.currentTimeMillis());
}
}
class MyThreadB extends TimerTask{
@Override
public void run() {
System.out.println("B run time="+System.currentTimeMillis());
}
}
class test{
public static void main(String[] args) throws Exception{
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
System.out.println("計(jì)劃時(shí)間為:"+nowTime);
MyThreadB myThreadB = new MyThreadB();
MyThreadA myThreadA = new MyThreadA();
Timer timer = new Timer();
timer.schedule(myThreadA,new Date(nowTime),4000);
timer.schedule(myThreadB,new Date(nowTime),4000);
Thread.sleep(10000);
timer.cancel();
System.out.println("任務(wù)全部取消了");
}
}
結(jié)果:
當(dāng)前時(shí)間:1616916352810
計(jì)劃時(shí)間為:1616916352810
A run time=1616916352810
B run time=1616916352810
B run time=1616916356818
A run time=1616916356818
A run time=1616916360820
B run time=1616916360820
任務(wù)全部取消了
Timer類中的cancel方法有時(shí)候不一定會(huì)停止計(jì)劃任務(wù),即任務(wù)正常執(zhí)行。
其原因是沒(méi)有搶到queue鎖,導(dǎo)致TimerTask中的任務(wù)正常執(zhí)行。
public class MyTask extends TimerTask {
private int i;
public MyTask(int i) {
this.i = i;
}
@Override
public void run() {
System.out.println("第"+i+"次沒(méi)有被取消");
}
}
class tests{
public static void main(String[] args) {
int i=0;
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
System.out.println("計(jì)劃時(shí)間為:"+nowTime);
while (true){
i++;
Timer timer = new Timer();
MyTask myTask = new MyTask(i);
timer.schedule(myTask,new Date(nowTime));
timer.cancel();
}
}
}
結(jié)果:
當(dāng)前時(shí)間:1616921790699
計(jì)劃時(shí)間為:1616921790699
第123次沒(méi)有被取消
第12802次沒(méi)有被取消
間隔執(zhí)行Task任務(wù)的算法
當(dāng)隊(duì)列中有3個(gè)任務(wù)ABC時(shí)這三個(gè)任務(wù)執(zhí)行的順序的算法是每次將最后一個(gè)任務(wù)放入隊(duì)頭,再執(zhí)行隊(duì)頭中的方法。其執(zhí)行順序效果如下:
1)ABC;
2)CAB;將C放入AB之前
3)BCA;將B放入CA之前
驗(yàn)證如下:
public class MyThreadA extends TimerTask {
@Override
public void run() {
System.out.println("A run time="+System.currentTimeMillis());
}
}
class MyThreadB extends TimerTask{
@Override
public void run() {
System.out.println("B run time="+System.currentTimeMillis());
}
}
class MyThreadC extends TimerTask{
@Override
public void run() {
System.out.println("C run time="+System.currentTimeMillis());
}
}
class test{
public static void main(String[] args) throws Exception{
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
System.out.println("計(jì)劃時(shí)間為:"+nowTime);
MyThreadA myThreadA = new MyThreadA();
MyThreadB myThreadB = new MyThreadB();
MyThreadC myThreadC = new MyThreadC();
Timer timer = new Timer();
timer.schedule(myThreadA,new Date(nowTime),2000);
timer.schedule(myThreadB,new Date(nowTime),2000);
timer.schedule(myThreadC,new Date(nowTime),2000);
Thread.sleep(Integer.MAX_VALUE);
}
}
測(cè)試結(jié)果:
當(dāng)前時(shí)間:1616917048998
計(jì)劃時(shí)間為:1616917048998
A run time=1616917049005
B run time=1616917049005
C run time=1616917049005
C run time=1616917051005
A run time=1616917051005
B run time=1616917051005
B run time=1616917053006
C run time=1616917053006
A run time=1616917053006
schedule(TimerTask task, long delay)
schedule(TimerTask task, long delay) 該方法的作用是以當(dāng)前的時(shí)間為參考時(shí)間在此時(shí)間上加上指定的延遲時(shí)間。
public class Run {
static public class myTask extends TimerTask{
@Override
public void run() {
System.out.println("開(kāi)始運(yùn)行了,時(shí)間為:"+System.currentTimeMillis());
}
}
public static void main(String[] args) {
myTask myTask = new myTask();
Timer timer = new Timer();
System.out.println("當(dāng)前時(shí)間:"+System.currentTimeMillis());
timer.schedule(myTask,5000);
}
}
結(jié)果:
當(dāng)前時(shí)間:1616922170729
開(kāi)始運(yùn)行了,時(shí)間為:1616922175739
運(yùn)行時(shí)間被延遲了5秒。
schedule(TimerTask task, long delay, long period)
schedule(TimerTask task, long delay, long period)該方法的作用是以當(dāng)前的時(shí)間為參考時(shí)間在此時(shí)間上加上指定的延遲時(shí)間,在以此時(shí)間間隔上無(wú)限的執(zhí)行某一任務(wù)。
public class Run {
static public class myTask extends TimerTask{
@Override
public void run() {
System.out.println("開(kāi)始運(yùn)行了,時(shí)間為:"+System.currentTimeMillis());
}
}
public static void main(String[] args) {
myTask myTask = new myTask();
Timer timer = new Timer();
System.out.println("當(dāng)前時(shí)間:"+System.currentTimeMillis());
timer.schedule(myTask,5000,2000);
}
}
結(jié)果:
當(dāng)前時(shí)間:1616922425863
開(kāi)始運(yùn)行了,時(shí)間為:1616922430879
開(kāi)始運(yùn)行了,時(shí)間為:1616922432879
開(kāi)始運(yùn)行了,時(shí)間為:1616922434899
開(kāi)始運(yùn)行了,時(shí)間為:1616922436909
scheduleAtFixedRate方法
scheduleAtFixedRate(TimerTask task, long delay, long period)該方法與 schedule(TimerTask task, long delay, long period) 這兩個(gè)方法的用法大致是一樣的。
scheduleAtFixedRate(TimerTask task, Date firstTime, long period)該方法與 schedule(TimerTask task, Date firstTime, long period) 這兩個(gè)方法的用法大致是一樣的。
但是他們之間也是有區(qū)別的。他們之間的區(qū)別就是是否具有追趕性。下面我們用兩個(gè)案例來(lái)測(cè)試他們的追趕性。
驗(yàn)證schedule()方法 不具有追趕性
public class Test6 {
static public class myTask extends TimerTask {
@Override
public void run() {
System.out.println("begin time:"+System.currentTimeMillis());
System.out.println("end time:"+System.currentTimeMillis());
}
}
public static void main(String[] args) {
myTask myTask = new myTask();
Timer timer = new Timer();
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
long runTime=nowTime-10000;
System.out.println("現(xiàn)在計(jì)劃執(zhí)行時(shí)間:"+runTime);
timer.schedule(myTask,new Date(runTime),2000);
}
}
結(jié)果;
當(dāng)前時(shí)間:1616923764405
現(xiàn)在計(jì)劃執(zhí)行時(shí)間:1616923754405
begin time:1616923764405
end time:1616923764405
begin time:1616923766406
end time:1616923766406
begin time:1616923768423
end time:1616923768423
begin time:1616923770426
end time:1616923770426
begin time:1616923772446
end time:1616923772446
從結(jié)果來(lái)看1616923754405時(shí)間到1616923764405這一時(shí)間的任務(wù)都沒(méi)有被執(zhí)行,這說(shuō)明schedule()方法不具有追趕性。
驗(yàn)證scheduleAtFixedRate()方法具有追趕性
public class Test6 {
static public class myTask extends TimerTask {
@Override
public void run() {
System.out.println("begin time:"+System.currentTimeMillis());
System.out.println("end time:"+System.currentTimeMillis());
}
}
public static void main(String[] args) {
myTask myTask = new myTask();
Timer timer = new Timer();
long nowTime=System.currentTimeMillis();
System.out.println("當(dāng)前時(shí)間:"+nowTime);
long runTime=nowTime-10000;
System.out.println("現(xiàn)在計(jì)劃執(zhí)行時(shí)間:"+runTime);
timer.scheduleAtFixedRate(myTask,new Date(runTime),2000);
}
}
結(jié)果:
當(dāng)前時(shí)間:1616924118955
現(xiàn)在計(jì)劃執(zhí)行時(shí)間:1616924108955
begin time:1616924118955
end time:1616924118955
begin time:1616924118955
end time:1616924118955
begin time:1616924118955
end time:1616924118955
begin time:1616924118955
end time:1616924118955
begin time:1616924118955
end time:1616924118955
begin time:1616924118955
end time:1616924118955
begin time:1616924120956
end time:1616924120956
begin time:1616924122955
end time:1616924122955
begin time:1616924124956
end time:1616924124956
begin time:1616924126955
end time:1616924126955
輸出時(shí)間1616924118955都是曾經(jīng)流逝時(shí)間的任務(wù)追趕,也就是將之前任務(wù)沒(méi)有執(zhí)行的任務(wù)追加執(zhí)行,將這10秒之內(nèi)的任務(wù)次數(shù)輸出完,再每間隔2秒執(zhí)行一次任務(wù)。將這兩段時(shí)間所對(duì)應(yīng)的任務(wù)彌補(bǔ)執(zhí)行,也就是在指定時(shí)間段內(nèi)的運(yùn)行次數(shù)必須運(yùn)行完整,這就是Task任務(wù)的追趕性。
————————————————
版權(quán)聲明:本文為CSDN博主「程序員小汪」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:
https://blog.csdn.net/weixin_44991304/article/details/115256074
鋒哥最新SpringCloud分布式電商秒殺課程發(fā)布
??????
??長(zhǎng)按上方微信二維碼 2 秒
感謝點(diǎn)贊支持下哈 
