自定义线程池

  1. 自定义线程池创建API
    线程池创建通过JUC的接口 Executor 实现, 平时我们使用其实现类 ThreadPoolExecutor 实现自定义线程池。
    常用构造函数:
        public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler) {
            if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
                throw new IllegalArgumentException();
            if (workQueue == null || threadFactory == null || handler == null)
                throw new NullPointerException();
            this.acc = System.getSecurityManager() == null ?
                    null :
                    AccessController.getContext();
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        }

     

  2. 参数详解
    corePoolSize:核心线程数。
    maximumPoolSize:最大线程数
    keepAliveTime:空闲最大存活时间
    unit:存活时间单位
    workQueue:任务缓存队列
    threadFactory:线程工厂类
    handler:拒绝策略
    线程池创建线程的规则:默认情况下,线程池创建时启动的线程为0,当任务执行时创建线程来执行任务,并发任务时,首先创建的线程数为设置的corePoolSize ,多余的任务存到 workQueue 队列中如果队列满了之后,且设置的 maximumPoolSize 大于 corePoolSize ,则会创建新的线程执行任务,对于大于 corePoolSize 数量的线程,再空闲 keepAliveTime 时间后会销毁线程。如果创建的线程达到 maximumPoolSize 还有并发任务等待,则会执行 设置的拒绝策略。

    这里有个点需要注意:只有队列满了之后才会创建新的线程数量至maximumPoolSize ,和执行拒绝策略,所以如果队列的大小必须是有界队列,这也是不使用 Executors 默认五种api创建线程池的原因。
  3. 自定义线程池创建demo 
    private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,16,10, TimeUnit.MINUTES, new ArrayBlockingQueue<>(400),
            Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
    这里设置的核心线程池10,最大线程池16,空闲线程时间10分钟,队列大小为400,默认工厂,抛出异常策略创建。
  4. 队列选择
  5. 线程工厂类
    线程工厂类顾名思义指定线程创建过程,默认的线程创建源码为:
        static class DefaultThreadFactory implements ThreadFactory {
            private static final AtomicInteger poolNumber = new AtomicInteger(1);
            private final ThreadGroup group;
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final String namePrefix;
    
            DefaultThreadFactory() {
                SecurityManager s = System.getSecurityManager();
                group = (s != null) ? s.getThreadGroup() :
                                      Thread.currentThread().getThreadGroup();
                namePrefix = "pool-" +
                              poolNumber.getAndIncrement() +
                             "-thread-";
            }
    
            public Thread newThread(Runnable r) {
                Thread t = new Thread(group, r,
                                      namePrefix + threadNumber.getAndIncrement(),
                                      0);
                if (t.isDaemon())
                    t.setDaemon(false);
                if (t.getPriority() != Thread.NORM_PRIORITY)
                    t.setPriority(Thread.NORM_PRIORITY);
                return t;
            }
        }

    主要是实现 ThreadFactory 实现 newThread 来指定创建线程的过程 ,从源码中我们可以看出,指定线程为用户线程(非守护线程),设置优先级为默认优先级。 使用 Thread的构造函数创建Thread对象。Thread的构造函数这里不展开介绍
    我们也可以自定义一个线程工厂类,例:
     

    public class NameThreadFactory implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            return thread;
        }
    }

    这里使用最简单方式演示,当然我们也可以使用类似默认线程池工厂类类似,指定名称,线程组更多属性。

  6. 拒绝策略
     当线程池的任务缓存队列已满,且线程池的线程数据达到maximumPoolSize 时,如果还会任务来到就会采用配置的拒绝策略,拒绝策略实现 RejectedExecutionHandler 接口,通过查看类结构可以看到线程池提供拒绝策略常用的有以下:

    ThreadPoolExecutor.AbortPolicy :丢弃任务并发抛出 RejectedExecutionException 异常 ;

    ThreadPoolExecutor.DiscardPolicy : 丢弃任务但是不抛出异常

    ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务

    ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理改任务
  7. 线程池简单使用
        /**
         * 异步发送消息
         *
         * @param msgReq
         * @return
         */
        public static boolean sendMsgAsync(MsgReq msgReq) {
            threadPoolExecutor.execute(() -> {
                sendMsgSync(msgReq);
            });
            return true;
        }

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值