Java線程池應用之ScheduledThreadPoolExecutor(含示例代碼)

ScheduledThreadPoolExecutor 繼承自 ThreadPoolExecutor,它主要用來在給定的延遲之後運行任務,或者定期執行任務。

public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory);
    }

ScheduledThreadPoolExecutor 的功能與 Timer 類似,但功能更強大、更靈活。Timer 對應的是單個後臺線程,而ScheduledThreadPoolExecutor 可以在構造函數中指定多個對應的後臺線程數。
Java 提供了多種類型的 ScheduledThreadPoolExecutor ,可以通過 Executors 創建,比較常見的有 ScheduledThreadPool、SingleThreadScheduledExecutor 等。適用於需要多個後臺線程執行週期任務,同時爲了滿足資源管理的需求而需要限制後臺線程數量的應用場景。

	static ThreadFactory threadFactory = new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").build();
    static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5, threadFactory);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1. 延遲 3 秒後執行 Runnable 方法
        scheduledExecutorService.schedule(() -> System.out.println("Hello World"), 3000, TimeUnit.MILLISECONDS);

        // 2. 延遲 3 秒後執行 Callable 方法
        ScheduledFuture<String> scheduledFuture = scheduledExecutorService.schedule(() -> "Hello ScheduledFuture", 3000, TimeUnit.MILLISECONDS);
        System.out.println(scheduledFuture.get());

        // 3. 延遲 1 秒後開始每隔 3 秒週期執行。
        //    如果中間任務遇到異常,則禁止後續執行。
        //    固定的頻率來執行某項任務,它不受任務執行時間的影響。到時間,就執行。
        scheduledExecutorService.scheduleAtFixedRate(() -> System.out.println("Hello ScheduleAtFixedRate"), 1, 3000, TimeUnit.MILLISECONDS);

        // 4. 延遲 1 秒後,每個任務結束延遲 3 秒後再執行下個任務。
        //    如果中間任務遇到異常,則禁止後續執行。
        //    受任務執行時間的影響,等待任務執行結束後纔開始計算延遲。
        scheduledExecutorService.scheduleWithFixedDelay(() -> System.out.println("Hello ScheduleWithFixedDelay"), 1, 3000, TimeUnit.MILLISECONDS);
    }

ScheduledThreadPoolExecutor 的執行步驟大抵如下:
1.當調用 ScheduledThreadPoolExecutor 的 scheduleAtFixedRate() 方法或者 scheduleWithFixedDelay()方 法時,會向 DelayedWorkQueue 隊列添加 ScheduledFutureTask 任務;
2.線程池中的線程從 DelayedWorkQueue隊列中獲取執行時間已到達的 ScheduledFutureTask,然後執行任務;
3.線程修改 ScheduledFutureTask 任務的執行時間爲下次將要被執行的時間;
4.線程把修改後的 ScheduledFutureTask 重新放回隊列。

在實際應用中,可將ScheduledThreadPoolExecutor用於服務端異步解決HTTP請求,避免高併發導致阻塞。示例代碼如下:

	private static final Logger logger = LoggerFactory.getLogger(PhoneController.class);
    private static ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1000,
            new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());

	@RequestMapping(value = "/getData")
    public HttpResult getData(@RequestBody CheckResultParam param) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                if (null != param && null != param.getData()) {
                    logger.info("Total Data Count: " + param.getData().size());
                    for (CheckDataParam data : param.getData()) {
                        logger.info("Data: " + JSON.toJSONString(data));
                    }
                }
            }
        });
        HttpResult result = new HttpResult("200", "Test", null);
        logger.info("Test getData");
        return result;
    }

注:使用BasicThreadFactory類需要引入org.apache.commons.lang3.concurrent.BasicThreadFactory

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章