先來看一段面試中的場景java
面試官: 我看你已經有必定工做年限了,那請問有沒有研究得比較深的一些技術棧呢?面試
你: 目前沒有太深的研究,暫時還主要是處於會使用的階段,我用過xxx,能幹活確定是沒問題的!分佈式
面試官: 那定時器在項目中有用過嗎,平時都是怎麼使用的?atom
你: 固然有,咱們是基於SpringBoot作的定時器,使用很簡單,就是打上註解就行.spa
面試官: 既然你有使用過,那咱們就聊一下SpringBoot定時器使用層面的問題,不問深的,甚至分佈式集羣也暫時不考慮了,就只考慮最簡單的
單線程模型
,那請問假如我定時任務是5秒執行一次,可是第一個任務就執行了8秒,第二個會怎麼樣呢?你詳細說一下各類狀況.線程
你: 這個...這個真沒有考慮過日誌
面試官: 我都還沒問原理,我這只是問最最基本的使用問題,要不今天先到這裏,你回去等通知吧.code
SpingBoot的定時器我相信你們都會使用,即便不會使用的,隨便搜索一下,相信都能在30分鐘內上手.可是其實Spring的定時器有三種模式,分別是fixedDelay
、cron
、fixedRate
.那這三種分別有什麼區別呢?咱們來分別寫一個SpringBoot的定時器Demo來體驗一下.cdn
fixedDelay方式blog
@Component
public class ScheduleHandle {
private final Logger log = LoggerFactory.getLogger(ScheduleHandle.class);
private List<Integer> index = Arrays.asList(8 * 1000, 3 * 1000, 6 * 1000, 2 * 1000, 2 * 1000);
private AtomicInteger atomicInteger = new AtomicInteger(0);
@Scheduled(fixedDelay = 3 * 1000)
public void fixedDelay() throws Exception {
int i = atomicInteger.get();
if (i < 5) {
Integer sleepTime = index.get(i);
log.info("第{}個任務開始執行,執行時間爲{}ms", i, sleepTime);
Thread.sleep(sleepTime);
atomicInteger.getAndIncrement();
}
}
}
複製代碼
該方式最簡單,在上一個任務執行完成以後,間隔3秒(由於@Scheduled(fixedDelay = 3 * 1000)
)後,執行下一個任務.這種是最容易理解的,因此放在第一個來說.用一個圖來表示的話,更容易理解.以下:
能夠用輸出日誌驗證上述結論
2019-04-07 21:59:11.761 INFO 29372 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第0個任務開始執行,執行時間爲8000ms
2019-04-07 21:59:22.772 INFO 29372 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第1個任務開始執行,執行時間爲3000ms
2019-04-07 21:59:28.777 INFO 29372 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第2個任務開始執行,執行時間爲6000ms
2019-04-07 21:59:37.783 INFO 29372 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第3個任務開始執行,執行時間爲2000ms
2019-04-07 21:59:42.785 INFO 29372 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第4個任務開始執行,執行時間爲2000ms
複製代碼
cron
@Scheduled(cron = "0/5 * * * * ? ")
public void cron() throws Exception {
int i = atomicInteger.get();
if (i < 5) {
Integer sleepTime = index.get(i);
log.info("第{}個任務開始執行,執行時間爲{}ms", i, sleepTime);
Thread.sleep(sleepTime);
atomicInteger.getAndIncrement();
}
}
複製代碼
由於上方代碼配置以下:
//每5s執行一次
@Scheduled(cron = "0/5 * * * * ? ")
複製代碼
所以你能夠理解爲5s就是一個週期.這就至關於在宿舍洗澡,由於只有一個洗澡位置(單線程),因此每次只能進去一我的,而後舍長在門口,每5s看一下有沒有空位,有空位的話叫下一個進去洗澡.
第5秒的時候,舍長看了一下,發現第一個同窗尚未出來.
第二個週期,也就是第10秒的時候再看一下.發現已經有空位了,那麼就叫第二個同窗進去洗.
第三個週期,也就是15秒的時候,又瞄了一眼,發現有空位了,叫第三個同窗進去洗.
第四個週期,也就是20秒的時候,發現沒有空位.
第五個週期的時候,也就是25秒的時候.發現有空位了,接着叫下一個進去洗.剩下的再也不分析.
用一張圖來表示以下:
能夠用輸出日誌驗證上述結論
2019-04-07 22:15:30.002 INFO 29385 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第0個任務開始執行,執行時間爲8000ms
2019-04-07 22:15:40.001 INFO 29385 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第1個任務開始執行,執行時間爲3000ms
2019-04-07 22:15:45.001 INFO 29385 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第2個任務開始執行,執行時間爲6000ms
2019-04-07 22:15:55.001 INFO 29385 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第3個任務開始執行,執行時間爲2000ms
2019-04-07 22:16:00.001 INFO 29385 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第4個任務開始執行,執行時間爲2000ms
複製代碼
fixedRate
@Scheduled(fixedRate = 5 * 1000)
public void fixedRate() throws Exception {
int i = atomicInteger.get();
if (i < 5) {
Integer sleepTime = index.get(i);
log.info("第{}個任務開始執行,執行時間爲{}ms", i, sleepTime);
Thread.sleep(sleepTime);
atomicInteger.getAndIncrement();
}
}
複製代碼
仍是要拿洗澡的這個例子來講.可是該方式和cron
的方式有很大不一樣
因上方代碼配置以下:
@Scheduled(fixedRate = 5 * 1000)
複製代碼
你能夠理解爲舍長預算每一個同窗洗澡的時間是5秒,可是第一個同窗進去洗澡,用了8秒.
第二個同窗原本應該在第5秒的時候就進去的,結果第一個同窗出來的時候,已是第8秒了,那麼舍長就趕忙催第二個同窗進去,把時間進度追回來.
第二個同窗知道時間緊,洗了3秒就出來.此時舍長髮現,第三個同窗,本來應該是在第10秒進去的,結果如今已經到了第11秒(8+3),那麼就趕忙催第三個同窗進去.
第三個同窗沉醉其中,難以自拔的洗了6秒.出來的時候已是第17秒(8+3+6).舍長掐指一算,發現第四個同窗本來應該是第15秒的時候就進去了.結果如今都17秒了,時間不等人,催促第四個同窗進去趕忙洗.
第四個同窗只洗了2秒就出來了,出來的時候,舍長看了一下時間,是第19秒."有原則"
的舍長髮現,第5個同窗本來預算是20秒的時候進去的,結果如今才19秒,不行,那讓他在外面玩1秒的手機,等20秒的時候再進去.
用一張圖來表示以下:
能夠用輸出日誌驗證上述結論
2019-04-07 22:18:44.814 INFO 29390 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第0個任務開始執行,執行時間爲8000ms
2019-04-07 22:18:52.819 INFO 29390 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第1個任務開始執行,執行時間爲3000ms
2019-04-07 22:18:55.824 INFO 29390 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第2個任務開始執行,執行時間爲6000ms
2019-04-07 22:19:01.829 INFO 29390 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第3個任務開始執行,執行時間爲2000ms
2019-04-07 22:19:04.816 INFO 29390 --- [pool-1-thread-1] com.toby.demo.job.ScheduleHandle : 第4個任務開始執行,執行時間爲2000ms
複製代碼
肥朝 是一個專一於 原理、源碼、開發技巧的技術公衆號,號內原創專題式源碼解析、真實場景源碼原理實戰(重點)。掃描下面二維碼關注肥朝,讓本該造火箭的你,再也不擰螺絲!