- ScheduledThreadPoolExecutor繼承自ThreadPoolExecutor。它主要用來在給定的延遲之后執(zhí)行任務(wù),或者定期執(zhí)行任務(wù)。
- ScheduledThreadPoolExecutor的功能與Timer類似炮车,但比Timer更強(qiáng)大,更靈活,Timer對應(yīng)的是單個(gè)后臺線程瘦穆,而ScheduledThreadPoolExecutor可以在構(gòu)造函數(shù)中指定多個(gè)對應(yīng)的后臺線程數(shù)纪隙。
1 創(chuàng)建ScheduledThreadPoolExecutor
- ScheduledThreadPoolExecutor通常使用工廠類Executors來創(chuàng)建,Executors可以創(chuàng)建兩種類型的ScheduledThreadPoolExecutor扛或,如下:
- (1)ScheduledThreadPoolExecutor:可以執(zhí)行并行任務(wù)也就是多條線程同時(shí)執(zhí)行绵咱。
- (2)SingleThreadScheduledExecutor:可以執(zhí)行單條線程。
1.1 ScheduledThreadPoolExecutor
創(chuàng)建ScheduledThreadPoolExecutor的方法構(gòu)造如下:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
1.2 SingleThreadScheduledExecutor
創(chuàng)建SingleThreadScheduledExecutor的方法構(gòu)造如下:
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
1.3 創(chuàng)建實(shí)例對象
創(chuàng)建實(shí)例對象代碼如下
ScheduledExecutorService scheduledThreadPoolExecutor=Executors.newScheduledThreadPool(5);
ScheduledExecutorService singleThreadScheduledExecutor=Executors.newSingleThreadScheduledExecutor();
2 ScheduledThreadPoolExecutor執(zhí)行機(jī)制分析
分析:DelayQueue是一個(gè)無界隊(duì)列告喊,所以ThreadPoolExecutor的maximumPoolSize在ScheduledThreadPoolExecutor中無意義麸拄。
ScheduledThreadPoolExecutor的執(zhí)行主要分為以下兩個(gè)部分
- (1)當(dāng)調(diào)用ScheduledThreadPoolExecutor的scheduleAtFixedRate()方法或者scheduleWithFixedDelay()方法時(shí),會向ScheduledThreadPoolExecutor的DelayQueue添加一個(gè)實(shí)現(xiàn)了RunnableScheduledFuture接口的ScheduleFutureTask黔姜。
- (2)線程池中的線程從DelayQueue中獲取ScheduleFutureTask拢切,然后執(zhí)行任務(wù)。
3 使用場景
3.1 ScheduledThreadPoolExecutor和SingleThreadScheduledExecutor的適用場景
- ScheduledThreadPoolExecutor:適用于多個(gè)后臺線程執(zhí)行周期性任務(wù)秆吵,同時(shí)為了滿足資源管理的需求而需要限制后臺線程數(shù)量的應(yīng)用場景淮椰。
- SingleThreadScheduledExecutor:適用于需要單個(gè)后臺線程執(zhí)行周期任務(wù),同時(shí)需要保證任務(wù)順序執(zhí)行的應(yīng)用場景纳寂。
4 ScheduledThreadPoolExecutor使用案例
我們創(chuàng)建一個(gè)Runnable的對象主穗,然后使用ScheduledThreadPoolExecutor的Scheduled()來執(zhí)行延遲任務(wù),輸出執(zhí)行時(shí)間即可:
4.1 該類延遲執(zhí)行的方法:
public ScheduledFuture schedule(Runnable command,long delay, TimeUnit unit);
參數(shù)解析:
- command:就是一個(gè)實(shí)現(xiàn)Runnable接口的類
- delay:延遲多久后執(zhí)行毙芜。
- unit:用于指定keepAliveTime參數(shù)的時(shí)間單位忽媒,這是一個(gè)枚舉,常用的有TimeUnit.MILLISECONDS(毫秒)腋粥,TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分鐘)等晦雨。
schedule
//創(chuàng)建一個(gè)工作線程繼承Runnable
public class WorkerThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start. Time = "+getNowDate());
threadSleep();
System.out.println(Thread.currentThread().getName()+" End. Time = "+getNowDate());
}
/**
* 睡3秒
*/
public void threadSleep(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 獲取現(xiàn)在時(shí)間
*
* @return 返回時(shí)間類型 yyyy-MM-dd HH:mm:ss
*/
public static String getNowDate() {
Date currentTime = new Date();
SimpleDateFormat formatter;
formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
String ctime = formatter.format(currentTime);
return ctime;
}
}
public class ScheduledThreadPoolTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
try {
//schedule to run after sometime
System.out.println("Current Time = "+getNowDate());
for(int i=0; i<3; i++){
Thread.sleep(1000);
WorkerThread worker = new WorkerThread();
//延遲5秒后執(zhí)行
scheduledThreadPool.schedule(worker, 10, TimeUnit.SECONDS);
}
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
scheduledThreadPool.shutdown();
while(!scheduledThreadPool.isTerminated()){
//wait for all tasks to finish
}
System.out.println("Finished all threads");
}
/**
* 獲取現(xiàn)在時(shí)間
*
* @return 返回時(shí)間類型 yyyy-MM-dd HH:mm:ss
*/
public static String getNowDate() {
Date currentTime = new Date();
SimpleDateFormat formatter;
formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
String ctime = formatter.format(currentTime);
return ctime;
}
}
線程任務(wù)確實(shí)在10秒延遲后才開始執(zhí)行。這就是schedule()方法的使用隘冲。
** scheduleAtFixedRate**
public ScheduledFuture scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)
scheduleAtFixedRate方法的作用是預(yù)定在初始的延遲結(jié)束后闹瞧,周期性地執(zhí)行給定的任務(wù),周期長度為period展辞,其中initialDelay為初始延遲奥邮。
scheduleWithFixedDelay
public ScheduledFuture scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit);
scheduleWithFixedDelay方法的作用是預(yù)定在初始的延遲結(jié)束后周期性地執(zhí)行給定任務(wù),在一次調(diào)用完成和下一次調(diào)用開始之間有長度為delay的延遲罗珍,其中initialDelay為初始延遲洽腺。
案例代碼
//周期函數(shù)測試類
public class ScheduledTask {
public ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(5);
public static void main(String[] args) {
new ScheduledTask();
}
public void fixedPeriodSchedule() {
// 設(shè)定可以循環(huán)執(zhí)行的runnable,初始延遲為0,這里設(shè)置的任務(wù)的間隔為1秒
for(int i=0;i<5;i++){
se.scheduleAtFixedRate(new FixedSchedule(), 0, 1, TimeUnit.SECONDS);
}
}
public ScheduledTask() {
fixedPeriodSchedule();
}
class FixedSchedule implements Runnable {
public void run() {
System.out.println("當(dāng)前線程:"+Thread.currentThread().getName()+" 當(dāng)前時(shí)間:"+new Date(System.currentTimeMillis()));
}
}
}
SingleThreadScheduledExecutor的使用的方法基本是類似