使用ThreadPoolTaskExecutor对任务进行异步阻塞处理

最近项目中要用到多线程处理任务,自然就用到了ThreadPoolTaskExecutor这个对象,这个是spring对于Java的concurrent包下的ThreadPoolExecutor类的封装,对于超出等待队列大小的任务默认是使用RejectedExecutionHandler去处理拒绝的任务,而这个Handler的默认策略是AbortPolicy,直接抛出RejectedExecutionException异常,这个不符合我们的业务场景,我希望是对于超出的任务,主线程进行阻塞,直到有可用线程,简单的代码如下

ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//默认线程池建立的线程数,当多余的线程处于空闲状态时,大于这个数字的线程会自动销毁
taskExecutor.setCorePoolSize(10);
//最大的线程数
taskExecutor.setMaxPoolSize(10);
//等待队列数,这里为了测试方便设置为0,实际可根据具体场景设置
taskExecutor.setQueueCapacity(0);
taskExecutor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (!executor.isShutdown()) {
            try {
                log.info("start get queue");
                executor.getQueue().put(r);
                log.info("end get queue");
            } catch (InterruptedException e) {
                log.error(e.toString(), e);
                Thread.currentThread().interrupt();
            }
        }
    }
}
);
taskExecutor.initialize();

for (int i = 0; i < 100; i++) {
    final int index = i;
    taskExecutor.execute(new Runnable() {
  
        @Override
        public void run() {
            try {
                log.info("thread start " + index);
                Thread.sleep(200000);
                log.info("thread end " + index);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });
}

结果输出:

INFO  2018-11-15 12:41:00,115 [scheduler-ssmQuartz_Worker-1] org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor: Initializing ExecutorService 
INFO  2018-11-15 12:41:00,116 [ThreadPoolTaskExecutor-1] com.bocsh.base.quartz.TimingCardUpdate: thread start 0
INFO  2018-11-15 12:41:00,116 [ThreadPoolTaskExecutor-2] com.bocsh.base.quartz.TimingCardUpdate: thread start 1
INFO  2018-11-15 12:41:00,116 [ThreadPoolTaskExecutor-3] com.bocsh.base.quartz.TimingCardUpdate: thread start 2
INFO  2018-11-15 12:41:00,116 [ThreadPoolTaskExecutor-4] com.bocsh.base.quartz.TimingCardUpdate: thread start 3
INFO  2018-11-15 12:41:00,116 [ThreadPoolTaskExecutor-5] com.bocsh.base.quartz.TimingCardUpdate: thread start 4
INFO  2018-11-15 12:41:00,117 [ThreadPoolTaskExecutor-6] com.bocsh.base.quartz.TimingCardUpdate: thread start 5
INFO  2018-11-15 12:41:00,117 [ThreadPoolTaskExecutor-7] com.bocsh.base.quartz.TimingCardUpdate: thread start 6
INFO  2018-11-15 12:41:00,117 [ThreadPoolTaskExecutor-9] com.bocsh.base.quartz.TimingCardUpdate: thread start 8
INFO  2018-11-15 12:41:00,117 [scheduler-ssmQuartz_Worker-1] com.bocsh.base.quartz.TimingCardUpdate: start get queue
INFO  2018-11-15 12:41:00,117 [ThreadPoolTaskExecutor-8] com.bocsh.base.quartz.TimingCardUpdate: thread start 7
INFO  2018-11-15 12:41:00,117 [ThreadPoolTaskExecutor-10] com.bocsh.base.quartz.TimingCardUpdate: thread start 9
INFO  2018-11-15 12:44:20,116 [ThreadPoolTaskExecutor-4] com.bocsh.base.quartz.TimingCardUpdate: thread end 3
INFO  2018-11-15 12:44:20,116 [ThreadPoolTaskExecutor-2] com.bocsh.base.quartz.TimingCardUpdate: thread end 1
INFO  2018-11-15 12:44:20,116 [ThreadPoolTaskExecutor-4] com.bocsh.base.quartz.TimingCardUpdate: thread start 10
INFO  2018-11-15 12:44:20,116 [ThreadPoolTaskExecutor-3] com.bocsh.base.quartz.TimingCardUpdate: thread end 2
INFO  2018-11-15 12:44:20,116 [ThreadPoolTaskExecutor-1] com.bocsh.base.quartz.TimingCardUpdate: thread end 0
INFO  2018-11-15 12:44:20,116 [scheduler-ssmQuartz_Worker-1] com.bocsh.base.quartz.TimingCardUpdate: end get queue
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-1] com.bocsh.base.quartz.TimingCardUpdate: thread start 11
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-6] com.bocsh.base.quartz.TimingCardUpdate: thread end 5
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-5] com.bocsh.base.quartz.TimingCardUpdate: thread end 4
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-7] com.bocsh.base.quartz.TimingCardUpdate: thread end 6
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-9] com.bocsh.base.quartz.TimingCardUpdate: thread end 8
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-10] com.bocsh.base.quartz.TimingCardUpdate: thread end 9
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-8] com.bocsh.base.quartz.TimingCardUpdate: thread end 7
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-3] com.bocsh.base.quartz.TimingCardUpdate: thread start 12
INFO  2018-11-15 12:44:20,117 [ThreadPoolTaskExecutor-2] com.bocsh.base.quartz.TimingCardUpdate: thread start 13
INFO  2018-11-15 12:44:20,117 [scheduler-ssmQuartz_Worker-1] com.bocsh.base.quartz.TimingCardUpdate: start get queue
INFO  2018-11-15 12:44:20,120 [scheduler-ssmQuartz_Worker-1] com.bocsh.base.quartz.TimingCardUpdate: end get queue
INFO  2018-11-15 12:44:20,120 [ThreadPoolTaskExecutor-8] com.bocsh.base.quartz.TimingCardUpdate: thread start 14
INFO  2018-11-15 12:44:20,120 [ThreadPoolTaskExecutor-10] com.bocsh.base.quartz.TimingCardUpdate: thread start 15
INFO  2018-11-15 12:44:20,120 [ThreadPoolTaskExecutor-5] com.bocsh.base.quartz.TimingCardUpdate: thread start 18
INFO  2018-11-15 12:44:20,120 [ThreadPoolTaskExecutor-7] com.bocsh.base.quartz.TimingCardUpdate: thread start 17
INFO  2018-11-15 12:44:20,120 [ThreadPoolTaskExecutor-9] com.bocsh.base.quartz.TimingCardUpdate: thread start 16
INFO  2018-11-15 12:44:20,120 [scheduler-ssmQuartz_Worker-1] com.bocsh.base.quartz.TimingCardUpdate: start get queue
INFO  2018-11-15 12:44:20,120 [ThreadPoolTaskExecutor-6] com.bocsh.base.quartz.TimingCardUpdate: thread start 19

可以看到,在任务超过线程池大小后,start get queue后会阻塞。
这里之所以能实现阻塞,是基于BlockingQueue的put方法来实现的,当阻塞队列满时,put方法会一直等待
参考文章: 让Java线程池实现任务阻塞执行的一种可行方案

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容