java线程池

java线程池

线程池的组成

一般线程池主要分一下部分:

  • 线程池管理器:用于创建并管理线程池
  • 工作线程:线程池中的线程
  • 任务接口:每个任务必须实现的接口,用于工作线程调度其运行
  • 任务队列:用于存放待处理的任务,提供一种缓冲机制

ThreadPoolExecutor(推荐)

ThreadPoolExecutor的构造器
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize, long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue)  {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
        Executors.defaultThreadFactory(), defaultHandler);
}
  • corePoolSize:指定了线程池中的线程数量。
  • maximumPoolSize:指定了线程池中的最大线程数量。
  • keepAliveTime:当前线程池数量超过 corePoolSize 时,多余的空闲线程的存活时间,即多次时间内会被销毁。
  • unit:keepAliveTime 的单位。
  • workQueue:任务队列,被提交但尚未被执行的任务。
  • threadFactory:线程工厂,用于创建线程,一般用默认的即可。
  • handler:拒绝策略,当任务太多来不及处理,如何拒绝任务。Java内置策略如下:
    • AbortPolicy : 直接抛出异常,阻止系统正常运行。
    • CallerRunsPolicy : 只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。显然这样做不会真的丢弃任务,但是,任务提交线程的性能极有可能会急剧下降。
    • DiscardOldestPolicy : 丢弃最老的一个请求,也就是即将被执行的一个任务,并尝试再次提交当前任务。
    • DiscardPolicy : 该策略默默地丢弃无法处理的任务,不予任何处理。如果允许任务丢失,这是最好的一种方案。

Java线程池工作过程

  1. 线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。
  2. 当调用 execute() 方法添加一个任务时,线程池会做如下判断:
  3. 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
    • 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列;
    • 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;
    • 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常 RejectExecutionException。
    • 当一个线程完成任务时,它会从队列中取下一个任务来执行。
  4. 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

注意:线程池刚创建时是没有线程的。也就是说,假设有一线程池,那么初始状态应该如下:

  • runingPoolSize = 0,正在运行的线程
  • corePoolSize = 1,核心线程个数
  • maximumPoolSize = 3 ,最大线程个数
  • keepAliveTime:60s
  • workQueue:ArrayBlockingQueue,有界阻塞队列,队列大小是4
  • handler:默认的策略,抛出来一个ThreadPoolRejectException

当没任务了,空闲的线程空闲时间超过60s,那么如果该线程为非核心线程将会被释放,也就是说保留下来的是核心线程。只有非核心的才会被释放。

网上的图片:

在这里插入图片描述

来源:https://www.cnblogs.com/gaopengpy/p/12149060.html

使用Executors创建四种线程池(不推荐直接使用)

Executors工厂类提供了四个静态方法,用于创建四种不同的线程池:

  • newCachedThreadPool
  • newFixedThreadPool
  • newScheduledThreadPool
  • newSingleThreadExecutor
为什么不推荐直接使用

这4个静态工厂方法内部都是通过new ThreadPoolExecutor()来创建的,虽然使用这4个静态工厂方法,隐藏了创建参数的复杂性,但是其设定的默认参数并不是十分合理,所以在阿里云开发手册中是不建议直接使用这4个方法来创建线程池的。就如newCachedThreadPool()创建的线程池是有可能导致OutOfMemoryError(堆溢出)。


newCachedThreadPool

创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。

函数源码

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • corePoolSize = 1,核心线程个数
  • maximumPoolSize = Integer.MAX_VALUE ,最大线程个数

也就是说newCachedThreadPool()开启的全是非核心线程,用多少开多少,60s空闲的会被回收。


newFixedThreadPool

创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。

函数源码

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
  • corePoolSize = n,核心线程个数
  • maximumPoolSize = n ,最大线程个数

也就是说newCachedThreadPool()开启的全是核心线程,并且LinkedBlockingQueue默认长度为Integer.MAX_VALUE。


newScheduledThreadPool

创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

函数源码

//---------------newScheduledThreadPool()----------------
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
}

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

//----------------------super----------------------
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
}
  • corePoolSize = n,核心线程个数

  • maximumPoolSize = Integer.MAX_VALUE ,最大线程个数

  • workQueue:DelayedWorkQueue,一个支持延时获取元素的无界阻塞队列。(延时功能应该是依赖这个队列实现的)


newSingleThreadExecutor

Executors.newSingleThreadExecutor()返回一个线程池(这个线程池只有一个线程),这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去!

函数源码

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  • corePoolSize = 1,核心线程个数
  • maximumPoolSize = 1 ,最大线程个数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程池是一种用于管理和复用线程的机制,它可以提高多线程应用程序的性能和效率。线程池中的线程可以被重复使用,避免了频繁创建和销毁线程的开销。 在Java中,线程池可以通过`ExecutorService`接口来创建和管理。线程池中的线程可以执行提交给它的任务,并且可以根据需要自动创建新的线程或销毁闲置的线程。 嵌套线程池是指在一个线程池中创建另一个线程池。这种情况通常发生在需要处理一些复杂的任务,其中每个任务本身也需要使用线程池来执行。 下面是一个示例代码,演示了如何在Java中嵌套使用线程池: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class NestedThreadPoolExample { public static void main(String[] args) { // 创建外层线程池 ExecutorService outerThreadPool = Executors.newFixedThreadPool(5); // 提交任务给外层线程池 outerThreadPool.execute(() -> { // 创建内层线程池 ExecutorService innerThreadPool = Executors.newFixedThreadPool(3); // 提交任务给内层线程池 innerThreadPool.execute(() -> { // 内层线程池执行的任务 System.out.println("Inner thread pool task executed"); }); // 关闭内层线程池 innerThreadPool.shutdown(); }); // 关闭外层线程池 outerThreadPool.shutdown(); } } ``` 在上面的示例中,我们首先创建了一个外层线程池`outerThreadPool`,它使用`Executors.newFixedThreadPool()`方法创建了一个固定大小的线程池。然后,我们向外层线程池提交了一个任务,该任务在执行时创建了一个内层线程池`innerThreadPool`,并向内层线程池提交了一个任务。最后,我们分别关闭了内层线程池和外层线程池

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值