讓Java線程池實現任務阻塞執行的一種可行方案


Java的線程池一般是基於concurrent包下的ThreadPoolExecutor類實現的,

不過當我們基於spring框架開發程序時,

通常會使用其包裝類ThreadPoolTaskExecutor,

這里有一個小問題就是當使用線程池執行任務的時候,

任務的消費速度小於生產速度時,任務通常會被阻塞到阻塞隊列,

而阻塞隊列大小通常是固定的,當阻塞隊列滿的時候,execute方法並不會阻塞,

默認是使用RejectedExecutionHandler去處理拒絕的任務,默認策略是AbortPolicy,直接拋出RejectedExecutionException異常,

很多情況下,這不符合我們的業務需求,我們希望被拒絕的任務能夠阻塞執行,從而阻止任務的生產速度;

一個比較巧妙的解決方案如下,僅供參考,具體還需要根據實際場景來應用:

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;


@Configuration
public class TaskExecutorConfig {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Bean("vgcThreadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(6);
        taskExecutor.setMaxPoolSize(50);
        taskExecutor.setQueueCapacity(1000);
        taskExecutor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor executor) -> {
                    if (!executor.isShutdown()) {
                        try {
                            executor.getQueue().put(r);
                        } catch (InterruptedException e) {
                            logger.error(e.toString(), e);
                            Thread.currentThread().interrupt();
                        }
                    }
                }
        );
        taskExecutor.initialize();
        return taskExecutor;
    }


}

這里之所以能實現阻塞,是基於BlockingQueue的put方法來實現的,當阻塞隊列滿時,put方法會一直等待...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM