博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA自定义阻塞型线程池
阅读量:5124 次
发布时间:2019-06-13

本文共 4056 字,大约阅读时间需要 13 分钟。

在编程过程中大家都接触过线程池吧,在JAVA中它的实现类是ThreadPoolExecutor,常见构造如下:

public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); }
  • corePoolSize: 线程池维护线程的最少数量
  • maximumPoolSize:线程池维护线程的最大数量
  • keepAliveTime: 线程池维护线程所允许的空闲时间
  • unit: 线程池维护线程所允许的空闲时间的单位
  • workQueue: 线程池所使用的缓冲队列
  • handler: 线程池对拒绝任务的处理策略

  正式使用中一般都会设置一个最大缓冲队列容量,如果线程池满它会对继续添加的任务线程执行指定的拒绝策略,ThreadPoolExcetor 的最后一个参数指定了拒绝策略,JDK提供了四种拒绝策略:

AbortPolicy 策略、CallerRunsPolicy策略、 DiscardOledestPolicy策略、DiscardPolicy策略。

AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作。

CallerRunsPolicy 策略:只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。

DiscardOleddestPolicy策略: 该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。

DiscardPolicy策略:该策略默默的丢弃无法处理的任务,不予任何处理。

  可以看到默认提供的四种策略似乎都不太友好,要么放弃要么抛异常,而直接在调用者线程中执行或许也不是你想要的,因为它破坏了线程的执行顺序。

有时候我们需要保证任务添加不会失败,并且只要被添加的任务能依次顺序执行就好了,而不需要这个添加动作立即响应,即让线程池等待池中的任务完成后再继续添加新任务,此时JDK提供的四种策略无法满足需求,

需要自定义拒绝策略,代码如下:

package com.montnets.task;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.RejectedExecutionHandler;import java.util.concurrent.ThreadFactory;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;/** * 自定义阻塞型线程池 当池满时会阻塞任务提交 *  * @ClassName: BlockThreadPool * @Description: TODO * @author: wangs * @date: 2018-1-24 下午5:24:54 */public class BlockThreadPool {    private ThreadPoolExecutor pool = null;        public BlockThreadPool(int poolSize) {        pool = new ThreadPoolExecutor(poolSize, poolSize, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue
(5), new CustomThreadFactory(), new CustomRejectedExecutionHandler()); } public void destory() { if (pool != null) { pool.shutdownNow(); } } private class CustomThreadFactory implements ThreadFactory { private AtomicInteger count = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); String threadName = BlockThreadPool.class.getSimpleName() + count.addAndGet(1); t.setName(threadName); return t; } } private class CustomRejectedExecutionHandler implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { try { // 核心改造点,由blockingqueue的offer改成put阻塞方法 executor.getQueue().put(r); } catch (InterruptedException e) { e.printStackTrace(); } } } public void execute(Runnable runnable) { this.pool.execute(runnable); } // 测试构造的线程池 public static void main(String[] args) { BlockThreadPool pool = new BlockThreadPool(3); for (int i = 1; i < 100; i++) { System.out.println("提交第" + i + "个任务!"); pool.execute(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getId() + "=====开始"); TimeUnit.SECONDS.sleep(10); System.out.println(Thread.currentThread().getId() + "=====【结束】"); } catch (InterruptedException e) { e.printStackTrace(); } } }); System.out.println("【提交第" + i + "个任务成功!】"); } // 2.销毁----此处不能销毁,因为任务没有提交执行完,如果销毁线程池,任务也就无法执行了 // exec.destory(); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } }}

  该类的核心实现还是ThreadPoolExecutor,只是自定义了拒绝策略CustomRejectedExecutionHandler,实现了阻塞功能。

当核心池和缓存队列满了之后外部再调用execute时就会阻塞住,一直等到池里某个任务完成后释放出空闲线程以后,再将该任务添加到缓存队列,而不会抛异常或丢弃该任务。

适用于一些定时扫描触发任务类场景。

多情为何忘情,无心怎去用心,空有知人之智,恨无自知之明。

 

转载于:https://www.cnblogs.com/sen-2017/p/8639165.html

你可能感兴趣的文章
iOS vs. Android,应用设计该如何对症下药?
查看>>
HTML第七章总结
查看>>
MySQL和Oracle的区别
查看>>
windows service 2008 内存吃尽解决方案
查看>>
sublime2使用和配置
查看>>
Visual Studio2012打开时弹出“遇到异常:这可能是由某个扩展导致的”错误的解决办法...
查看>>
IDEA设置取消自动显示参数提示
查看>>
84. Largest Rectangle in Histogram
查看>>
MySQL-5.7.21非图形化下载、安装、连接问题记录
查看>>
RabbitMQ 声明Queue时的参数们的Power
查看>>
中国经济怎么办之我见
查看>>
什么是REST API?
查看>>
目标检测近5年发展历程概述(转)
查看>>
14. Java基础之泛型
查看>>
spring----06 更多DI知识
查看>>
FFmpeg开发实战(三):FFmpeg 打印音视频Meta信息
查看>>
OSGI(面向Java的动态模型系统)
查看>>
精通 ASP.NET MVC 4 学习笔记(一)
查看>>
laravel框架的数据库链接
查看>>
Unity预计算全局实时GI(gi params)
查看>>