JDK 线程池

JDK 线程池


线程池参数

在JDK的4种线程池之前, 先介绍一下线程池的几个参数

  • corePoolSize 线程池的核心线程数量,
  • maximumPoolSize 线程池的最大线程数量
  • keepAliveTime 线程被回收的最大空闲时间
  • keepAliveTime 的单位(ms、s、...)
  • BlockingQueue 任务队列,存放任务
  • ThreadFactory 线程工厂

  • RejectedExecutionHandler 线程池拒绝策略(当任务过多的时候,线程池拒绝任务的方式)
  • allowCoreThreadTimeOut 允许核心线程池被回收, 默认 false, so 默认情况下 核心线程并不会被回收掉.


JDK 提供的四种线程池介绍

newFixedThreadPool

固定线程池数量, 核心线程数 = 最大线程数

任务队列: LinkedBlockingQueue(Integer.MAX_VALUE) 无界队列

适用于同时处理固定任务数的场景.

    public static ExecutorService newFixedThreadPool(int nThreads) {
          // coreThreads = maxThreads
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }


newCachedThreadPool

核心线程数为0, 最大为 Integer.MAX_VALUE,也就是当任务足够多的时候, 可以无限增加线程.

任务队列: SynchronousQueue 默认传入参数 fair=false, 即处理任务非公平.

适用于处理小任务

      public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

SynchronousQueue

       public SynchronousQueue(boolean fair) {
        // fair = true 则会按照FIFO先入先出的顺序执行 
        // fair = false 则优先取出最新添加的任务, 如果任务多的话,最先添加的任务反而执行不到
        transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
    }


newSingleThreadExecutor

单个线程的线程池

任务队列: LinkedBlockingQueue 同样是无界队列

适用于需要将任务按顺序执行的时候

        public static ExecutorService newSingleThreadExecutor() {
        // 核心线程数=最大线程数=1
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }


newScheduledThreadPool

固定核心线程数, 线程数量不会再增长, maximumPoolSize 这个参数对定时线程池没有作用.

任务队列: DelayedWorkQueue 无界队列, 这是 ScheduledThreadPoolExecutor 的一个内部类

适用于有延时 或者定时需求的场景

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


线程拒绝策略

AbortPolicy

拒绝新任务,并且抛出异常, 默认的拒绝策略

    public static class AbortPolicy implements RejectedExecutionHandler {
        public AbortPolicy() { }
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            // 直接抛出异常 
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }


CallerRunsPolicy

当拒绝任务的时候,由调用线程处理该任务.

        public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public CallerRunsPolicy() { }
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            // 如果线程池未停止
            if (!e.isShutdown()) {
                  // 当前线程直接调用任务的run方法
                r.run();
            }
        }
    }


DiscardPolicy

拒绝新任务,静悄悄的将新任务丢弃,而不通知(太坑了吧), 具体看它的代码也是什么事情都没做, 还真的就直接丢弃任务了.

    public static class DiscardPolicy implements RejectedExecutionHandler {
        public DiscardPolicy() { }
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
          // 任务被拒绝后,啥事情都不干
        }
    }


DiscardOldestPolicy

当任务满时, 抛弃旧的未处理的任务, 然后重新执行 execute 方法(此过程会重复), 除非 线程池 停止运行, 这种情况任务将被丢弃.具体看代码

     public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public DiscardOldestPolicy() { }
                public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                    // 如果线程池停止, 直接丢弃任务,不做任何处理
            if (!e.isShutdown()) {
               // 丢弃一个任务队列中的任务
               e.getQueue().poll();
               // 重新执行被拒绝的任务, 如果再次被拒绝, 则会一直重复这个过程
               e.execute(r);
            }
        }
   }

猜你喜欢

转载自www.cnblogs.com/wuhaonan/p/11754251.html