Java线程池 通过ThreadPoolExecutor构造器认识四种线程池

ThreadPoolExecutor构造器

  • int corePoolSize: 核心线程池大小
  • int maxnumPoolSize: 最大线程池大小
  • long keepAliveTime :超时时间(超时了没有人调用就会释放)
    • 特点注意: 这个超时时间控制的时非核心线程数的回收时间,核心线程永远不会被回收
  • TimeUnit unit: 超时单位
  • BlockingQueue< Runnable> workQueue: 阻塞队列(当前没有空闲线程时,任务会放入阻塞队列)
  • ThreadFactory threadFactory: 线程工厂,用来创建线程
  • RejectedExecutionHandler handler: 拒绝策略
 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;
    }

线程池类型

一般通过Executors 工具类创建线程池

SingleThreadExecutor
  • 一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,任务按照阻塞队列先进先出的顺序执行
  • 通过源码发现,SingleThreadExecutor的参数:
    • corePoolSize = 1 : 核心线程池大小为1
    • maxnumPoolSize = 1 : 最大线程池大小也为1
    • keepAliveTime = 0 : 非核心线程空闲时立刻释放(SingleThreadExecutor不会有非核心线程,因为maxnumPoolSize=corePoolSize=1,所以该参数忽略)
    • workQueue = new LinkedBlockingQueue(): 基于链表实现的阻塞队列,队列最大可容纳Integer.MAX_VALUE个任务
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
FixedThreadPool
  • 一个固定大小的线程池,corePoolSize=maxnumPoolSize,即核心线程数等于最大线程数
  • 如果当前运行的线程数少于corePoolSize,会立刻创建新线程执行任务,否则将任务加入到LinkedBlockingQueue中
  • 用户可以指定线程池的大小
  • 优点: 效率高,节省了创建线程的开销
  • 缺点: 不会释放工作线程,会占用一定的系统资源
 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
CachedThreadPool
  • 可缓存线程池,一个可根据需要无限(其实最大为21亿)创建新线程的线程池.
  • 如果当前没有线程可用,会创建一个新的线程来执行任务;如果还有执行完没有被销毁的线程,就会复用该线程.
  • 当有线程空闲超过一分钟后,该线程被回收释放
  • 适用场景:
    • 耗时较短的任务
    • 任务处理速度 > 任务提交速度
  • 通过源码,CachedThreadPool参数如下:
    • corePoolSize =0 :核心线程池大小为0
    • maxnumPoolSize = Integer.MAX_VALUE:线程池最大线程数为21亿
    • keepAliveTime = 60L : 非核心线程空闲存活时间为60,单位为秒(即一分钟)
    • workQueue = new SynchronousQueue(): 是一个没有数据缓冲的阻塞队列,内部没有任何存放元素的能力.每次只能put(放入)一个任务,第二次put时会被阻塞,直到take操作(取出)任务为止.同时take操作在队列为空时也处于阻塞状态
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
ScheduleThreadPool
  • 周期任务池(延迟任务池),主要用来在给定的延迟之后运行任务,或者定期执行任务,在功能上与Timer(定时器)类似
  • 参数定义说明:
    • corePoolSize :核心线程池大小由用户自定义
    • maxnumPoolSize = Integer.MAX_VALUE:线程池最大线程数为21亿
    • keepAliveTime =0 : 非核心空闲线程立刻回收释放
    • workQueue = new DelayedWorkQueue() :一个优先级队列,按照任务延时时间的不同进行排序,延时时间越短地就排在队列的前面,先被获取执行。
//为了实现周期调度功能,ScheduleThreadPool的实现和前三种线程池实现不太一样
public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService {

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        //调用了父类ThreadPoolExecutor的构造方法
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }
}
### Java 中 `ThreadPoolExecutor` 类的使用方法 #### 创建自定义线程池并执行任务 通过继承 `CustomThreadPool` 并实现其功能来展示如何创建和配置一个简单的线程池。下面的例子展示了如何初始化具有两个核心线程数目的线程池,并向其中提交五个任务。 ```java package com.howtodoinjava.threads; public class CustomThreadPoolExample { public static void main(String[] args) { // 初始化带有2个工作线程的核心线程池 CustomThreadPool customThreadPool = new CustomThreadPool(2); for (int i = 1; i <= 5; i++) { Task task = new Task("Task " + i); System.out.println("Created : " + task.getName()); // 提交任务给线程池去执行 customThreadPool.execute(task); } } } ``` 此代码片段说明了如何构建基本的任务调度框架[^1]。 #### 利用标准库中的工具简化线程池管理 为了更方便地管理和操作线程池,可以借助于 `Executors` 工具类提供的静态工厂方法。这些方法允许快速设置不同类型的预设线程池实例,而无需手动指定所有的参数细节。 ```java import java.util.concurrent.*; // 使用 Executors 来获取固定大小的线程池 ExecutorService executor = Executors.newFixedThreadPool(4); for(int i=0;i<10;i++){ Runnable worker = new WorkerThread("" + i); // 将任务交给线程池处理 executor.execute(worker); } // 关闭线程池以防止新任务被接受 executor.shutdown(); while (!executor.isTerminated()) {} System.out.println("Finished all threads"); ``` 这段程序利用了 `newFixedThreadPool()` 方法来获得拥有四个工作线程的标准线程池对象[^2]。 #### 定义具体的工作单元——事件处理器 当涉及到具体的业务逻辑时,则可以通过像 `EventHandler.handle()` 这样的函数来进行封装。每当有新的工作任务到来时,就可以调用该方法完成相应的数据处理流程。 ```java public class WorkEvent { private String workNo; // 构造器和其他成员省略... public String getWorkNo(){ return this.workNo; } } public class EventHandler { /** * 处理业务 */ public static void handle(WorkEvent workEvent){ System.out.println("正在处理,workNo=[" + workEvent.getWorkNo() + "]"); } } ``` 上述代码段描述了一个典型的业务场景下的任务接收与响应机制[^3]。 #### 结合实际案例理解概念 对于初学者来说,观看一些关于 `ThreadPoolExecutor` 应用的教学视频可能会更加直观易懂。例如,在 Bilibili 上有一个专门介绍这个主题的内容可以帮助加深印象[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值