线程池
线程池即在池子中存放的是线程本身,当程序启动时就创建出若干个线程,如果有任务就处理,没有任务就阻塞等待。
线程池的参数
- int corePoolSize 核心线程数,创建线程池时包含的最小线程数量。
- int maximumPoolSize 最大线程数(临时线程数),当核心线程数不够用时,允许系统可以创建的最多线程数是多少。
- long keepAliveTime 临时线程空闲的时长
- TimeUnit unit 空闲的时间单位,与keepAliveTime一起使用
- BlockingQueue workQueue 用来保存任务的阻塞队列
- ThreadFactory threadFactory 线程工厂,如何去创建线程,用系统默认的就可以。
- RejectedExecutionHandler handler 拒绝策略,触发的时机:当线程池处理不了过多的任务时。
线程池的工作流程
- 当任务添加到线程池时,先判断任务数是否大于核心线程数
- 当小于时,直接由核心线程处理,否则加入阻塞队列
- 当阻塞队列满了之后,会按照指定的线程最大数创建临时线程
- 此时会从阻塞队列中取出任务,放到临时线程中处理
- 当阻塞队列满了,临时线程也创建完成且都在处理任务时,就会执行拒绝策略
- 当任务减少,临时线程达到空闲时长,就会被回收
使用Executors 创建常见的线程池
public static void main(String[] args) {
// 1.用来处理大量短时间工作任务的线程池,如果池中没有可用的线程将创建新线程,如果线程空闲60s将收回并移出缓存
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// 2.创建一个操作无界队列且固定大小线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
// 3.创建一个操作无界队列且只有一个工作线程的线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
// 4.创建一个单线程执行器,可以在给定时间后执行或定期执行
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
// 5.创建一个给定大小的线程池,可以在给定时间后执行或定期执行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
// 6.创建一个指定大小(不传入参数,为当前机器CPU核心数)的线程池,并行地处理任务,不保证处理顺序
Executors.newWorkStealingPool();
}
线程池的优点
- 降低资源消耗: 减少线程的创建和销毁带来的性能开销
- 提高响应速度: 当任务来时可以直接处理,不用等待线程创建
- 可管理性: 进行统一的分配,监控,避免大量的线程间因互相抢占系统资源导致的阻塞现象