2018年7月9日08:48:58
歡迎掃二維碼關注公衆号,擷取技術幹貨
【1】前言
線程池與任務定時執行,一是項目随處可見的一種技術,二是自己還需打打紮實基礎;不可以僅僅局限于業務的實作,要去體會底層的思想;
【2】關于線程池ThreadPoor與Timer的使用
2.1 Java提供的Time類可以周期性地或者延期執行任務,但是有時我們需要并行執行同樣的任務,這個時候如果建立多個Time對象會給系統帶來負擔,解決辦法是将定時任務放到線程池中執行。
Java的ScheduledThreadPoolExecutor類實作了ScheduledExecutorService接口中定義的以不同方法執行任務的方法。
2.2 ScheduleThreadPoolExecutor與Timer相比的優勢
(1)Timer是基于絕對時間的延時執行或周期執行,當系統時間改變,則任務的執行會受到的影響。而ScheduleThreadPoolExecutore中,任務時基于相對時間進行周期或延時操作。
(2)Timer也可以送出多個TimeTask任務,但隻有一個線程來執行所有的TimeTask,這樣并發性受到影響。而ScheduleThreadPoolExecutore可以設定池中線程的數量。
(3)Timer不會捕獲TimerTask的異常,隻是簡單地停止,這樣勢必會影響其他TimeTask的執行。而ScheduleThreadPoolExecutore中,如果一個線程因某些原因停止,線程池可以自動建立新的線程來維護池中線程的數量。
2.3 自jdk1.5開始,Java開始提供ScheduledThreadPoolExecutor類來支援周期性任務的排程,在這之前,這些工作需要依靠Timer/TimerTask或者其它第三方工具來完成。但Timer有着不少缺陷,如Timer是單線程模式,排程多個周期性任務時,如果某個任務耗時較久就會影響其它任務的排程;如果某個任務出現異常而沒有被catch則可能導緻唯一的線程死掉而所有任務都不會再被排程。ScheduledThreadPoolExecutor解決了很多Timer存在的缺陷。JDK1.5之前的Timer和TimerTask類已經過時了。
通過如上的介紹,可以對比一下Timer和ScheduledThreadPoolExecutor:
Timer | ScheduledThreadPoolExecutor |
單線程 | 多線程 |
單個任務執行時間影響其他任務排程 | 多線程,不會影響 |
基于絕對時間 | 基于相對時間 |
一旦執行任務出現異常不會捕獲,其他任務得不到執行 | 多線程,單個任務的執行不會影響其他線程 |
是以,在JDK1.5之後,應該沒什麼理由繼續使用Timer進行任務排程了。
【3】ScheduledThreadPoolExecutor 工作原理
【4】源碼
【5】實作例子
BusinessPool.java:
package test2;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class BusinessPool {
private ScheduledThreadPoolExecutor executor;
BusinessPool() {
}
public static class BusinessPoolThreadFactory implements ThreadFactory {
final ThreadGroup group = Thread.currentThread().getThreadGroup();
final AtomicInteger threadNumber = new AtomicInteger(1);
final String namePrefix = "business-pool";
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
public void init() {
this.executor = new ScheduledThreadPoolExecutor(1, new BusinessPoolThreadFactory());
}
public void schedule(Runnable runnable, long delay, TimeUnit unit) {
executor.schedule(runnable, delay, unit);
}
public void execute(Runnable runnable) {
executor.execute(runnable);
}
}
test.java:
package test2;
import java.util.concurrent.TimeUnit;
public class test23 {
public static void main(String[] args) {
BusinessPool businessPool = new BusinessPool();
businessPool.init();
businessPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("Hello world 0_0|||");
}
}, 3, TimeUnit.SECONDS);
}
}
輸出結果(延時3s執行線程):
Hello world 0_0|||
參考博文:https://www.jianshu.com/p/925dba9f5969