专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java线程池总结

temp10 2025-05-23 20:01:21 java教程 3 ℃ 0 评论

1. 为什么要使用线程池

线程池的工作主要是控制线程的数量。处理过程中将任务放入等待队列,然后在线程创建后执行这些任务。

优点:线程复用,控制最大并发数,管理线程

Java线程池总结

2. JDK提供的线程池

主要关注两个类:

ThreadPoolExecutor:线程池核心类

Executors:创建线程池的工具类

通过Executors工具类创建线程池的3种方式

  • 创建线程数固定的线程池
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
  • 创建单线程的线程池
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

Single线程池可以理解为Fixed线程池的特例

  • 创建可缓冲线程的线程池
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

通过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.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

ThreadPoolExecutor构造方法的7大参数

corePoolSize:线程池中常驻的核心线程数

maximumPoolSize:线程池中可容纳的最大线程数

keepAliveTime:空闲的临时线程的存活时间(当线程池中的线程数量超过corePoolSize时,临时创建的线程如果空闲时长达到keepAliveTime,那么该临时线程将被销毁,直到只剩corePoolSize个线程为止)

unit:keepAliveTime的单位

workQueue:缓存任务的队列

threadFactory:创建线程的工厂

handler:拒绝策略(当缓存队列已满,且线程池中的线程数也达到了最大线程数,此时应该采用何种策略拒绝新来的任务)

3. 线程池底层逻辑

  1. 线程池初始化后不会立即创建线程,而是等到有任务来时才创建核心线程。
  2. 当线程池中核心线程数已满后并不会立即扩容线程池,而是把任务放到等待队列中。
  3. 当等待队列已满后,创建临时线程执行任务,直到总线程数达到maximumPoolSize为止。
  4. 如果等待队列已满且总线程数达到最大值后还有任务进来,则按照设置的拒绝策略处理。
  5. 当总线程数大于核心线程数时,空闲的临时线程等待keepAliveTime(unit)后将自动销毁。

4. 线程池需要手工创建

JDK中的Executors工具类定义了一些快捷地创建线程池的方法,但是《阿里巴巴Java开发手册》中提到,我们应该禁止使用这些方法来创建线程池,而应该手动通过new ThreadPoolExecutor来创建线程池。

原因如下:

(七) 并发处理

4.【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明:Executors返回的线程池对象的弊端如下:

1) FixedThreadPool和SingleThreadPool:

允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。

2) CachedThreadPool:

允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表