Java线程池

最核心代码: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;
}
  • workQueue :任务队列
    • SynchronousQueue:该队列不存储任务,直接提交给线程
    • ArrayBlockingQueue:基于数组的有界队列,先进先出原则
    • LinkedBlockingQueue:基于链表的有界队列,先进先出原则
  • handler:饱和策略
    • AbortPolicy:丢弃任务并抛出RejectedExecutionException异常
    • DiscardPolicy:丢弃任务,但不抛出异常
    • DiscardOldestPolicy:丢弃队列最前面的任务,并执行新传入的任务
    • CallerRunsPolicy:线程池的所在的线程去执行任务

以上是线程池最核心内容

接下来我们看看Executors中的几个创建线程池的方法方法,就是基于核心new ThreadPoolExecutor创建线程池


单线程线程池:newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}

核心线程1,最大线程1(无非核心线程),空闲线程失效时间为0,队列的最大长度为Integer.MAX_VALUE(0x7fffffff)

缺点:队列容量过大,可能会堆积大量的任务,从而造成OOM

固定数量线程池:newFixedThreadPool

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

public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}

核心线程nThreads,最大线程nThreads(无非核心线程),空闲线程失效时间为0,队列的最大长度为Integer.MAX_VALUE(0x7fffffff)

缺点:队列容量过大,可能会堆积大量的任务,从而造成OOM

缓存线程池:newCachedThreadPool

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

核心线程0,最大线程为Integer.MAX_VALUE(0x7fffffff全是非核心线程),空闲线程失效时间为60秒,队列为SynchronousQueue,表示不存储任务,直接让线程去执行

缺点:最大线程数过大,可能会创建大量线程,从而造成OOM

总结

阿里开发文档不推荐使用Executors来创建线程,会有内存溢出的可能性。 开发者通过ThreadPoolExecutor创建,自定义线程池的参数,这样可以避免一些已知的问题。

线程数配置推荐

CPU密集型:核心线程数 = CPU核数 + 1
IO密集型:核心线程数 = CPU核数 * 2
posted @ 2021-03-26 10:39  yzwine  阅读(86)  评论(0)    收藏  举报