java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java线程池ThreadPoolExecutor

Java的线程池ThreadPoolExecutor及多种线程池实现详解

作者:好奇的7号

这篇文章主要介绍了Java的线程池ThreadPoolExecutor及多种线程池实现详解,ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量,之所以将信息存储在一个变量中,是为了保证原子性,需要的朋友可以参考下

1、线程池状态含义

ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量,之所以将信息存储在一个变量中,是为了保证原子性。

具体的高三位与线程池状态如下,引用自网课的图片:

2、构造方法的参数、具体工作方式

public ThreadPoolExecutor(
    int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,
    ThreadFactory threadFactory,
    RejectedExecutionHandler handler)

对于以上变量,其含义如下:corePoolSize 核心线程数目 (最多保留的线程数)

具体解释:

1.核心线程数:是指在线程池中始终保持存活的线程数量。在线程池中,当有新的任务到达时,线程池会创建新的线程来处理任务,但是当任务处理完毕后,线程并不会立即销毁,而是被放置在线程池中等待下一个任务的到来。 当将allowCoreThreadTimeout设置为 true 时,核心线程也会超时回收,像这样:

executor.allowCoreThreadTimeOut(true); // 允许回收核心线程

2.最大线程数目:指核心线程数+非核心线程数的总数。例如设置核心为5,最大为10,那么非核心(救急)则为10-5=5个

3.生存时间:线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将allowCoreThreadTimeout设置为 true 时,核心线程也会超时回收。

4.阻塞队列:如果核心线程都被占用没有空闲,此时又多来了新任务,则新来的任务会被加入阻塞队列阻塞等待。

5.拒绝策略:如果阻塞队列满了,继续来任务,那么就创建救急线程来执行新任务,但如果救急线程也不够(达到最大线程数),再来任务,因为线程池已经填满了到极限了,所以就要拒绝新来的任务了。jdk和各种框架有多种拒绝策略的实现:

3、线程池有哪些常用的实现方式

3.1 newFixedThreadPool

全是、多个核心线程不回收

fixed,即“固定的”,线程数固定,能够控制线程的最大并发数:

(1)源码中,其核心线程数和最大线程数都是nThreads,即相等,说明没有非核心线程

(2)阻塞队列是无界的,可以放任意数量的任务。

(3)核心线程不会自动回收,直到被明确打断:“The threads in the pool will exist until it is explicitly shutdown.”

public static ExecutorService newFixedThreadPool(int nThreads) {
     return new ThreadPoolExecutor(nThreads, nThreads,
     0L, TimeUnit.MILLISECONDS,
     new LinkedBlockingQueue<Runnable>());
}
//具体使用示例
//1.创建定长线程池对象,线程数量固定为3
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
//2. 创建Runnable线程对象以及执行的任务
Runnable task =new Runnable(){
  public void run() {
     System.out.println("执行任务啦");
  }
};
//3. 向线程池提交任务
fixedThreadPool.execute(task);

3.2newCachedThreadPool

全是非核心,定时回收

Cached,缓存,是说这种线程池的实现像缓存一样是可变的:

(1)核心线程数是 0, 最大线程数是 Integer.MAX_VALUE,线程的空闲生存时间是 60s,意味着:这种线程池内都是非核心线程、可以无限创建、定时60s回收。

(2)队列采用了 SynchronousQueue ,特点是,它没有容量,没有线程来取是放不进去的。

(3)适合场景:执行大量、耗时少的任务。

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

3.3newSingleThreadExecutor

就一个核心线程,不回收

Single,即单线程的线程池:只有 1 个核心线程,无非核心线程,执行后不会立即回收。 这样相当于顺序执行,不需要处理线程同步问题。

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

3.4newScheduledThreadPool

核心非核心都有,非核心定时回收

Scheduled即定时的:核心线程数量固定,非核心线程数量无限多但会定时回收,当非核心线程执行完闲置 10ms 后则回收,任务队列为延时阻塞队列。 应用场景:执行定时或周期性的任务。

private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;

到此这篇关于Java的线程池ThreadPoolExecutor及多种线程池实现详解的文章就介绍到这了,更多相关Java线程池ThreadPoolExecutor内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文