Java基础--线程池
简介
线程池可以重用存在的线程,减少对象创建、消亡的开销,性能好。并且可以控制最大并发线程数,提高系统资源利用率,同时避免过多资源竞争,避免阻塞。
java.uitl.concurrent.ThreadPoolExecutor
ThreadPoolExecutor提供了四个构造函数:
1 | public ThreadPoolExecutor(int corePoolSize, |
- corePoolSize //核心线程数量;只有任务来到才会创建线程。
- maximumPoolSize //线程最大线程数量
- workQueue //阻塞队列,存储等待执行的任务
- keepAliveTime //线程中没有任务时,线程最多保持多久就销毁
- unit //的时间单位
- threadFactory //线程工厂,用来创建线程
- rejectHandler //如果阻塞队列满了,并且没有空闲线程,根据这个参数执行拒绝处理任务的策略
1、如果系统中线程数量小于corePoolSize,直接创建新的线程来执行任务(不管是否存在空闲线程);如果线程数量大于corePoolSize,但是小于maximumPoolSize,只有workQueue满了才会创建新的线程;如果系统中线程数量等于maximumPoolSize,maximumPoolSize和corePoolSize相同,workQueue不满,则线程进入workQueue,否则指定策略执行任务。
2、workQueue 是阻塞队列(BlockingQueue)
1 | ArrayBlockingQueue //可以限定队列长度 |
核心参数
- execute() //提交任务,交给线程池使用
- submit() //提交任务,能够返回执行结果 execute + Future
- shutdown() // 关闭线程池,等所有任务都执行完
- shutdownNow() //关闭线程池,不等待任务执行完
- getTaskCount() //线程池已执行和未执行的任务总数
- getCompletedTaskCount() //已完成任务数量
- getPoolSize() //线程池当前线程数量
- getActiveCount() //当前线程池中正在执行任务的线程数量
线程池原理
线程池状态
- RUNNING 运行状态,能接受新提交的任务,也能处理阻塞队列中的任务
- SHUTDOWN 关闭状态,不能接受新提交的任务,但是可以处理阻塞队列中的任务
- STOP 不能接受新的任务,也不能处理阻塞队列中的任务
- TIDYING 工作线程为0时进入这个状态
线程池种类
- Executors.newCachedThreadPool
- Executors.newFixedThreadPool
- Executors.newSingleThreadExecutor
- Executors.newScheduleThreadPool
newCachedThreadPool
创建一个可缓存的线程池,任务增加时则创建线程执行任务,线程空闲60秒则回收线程。
1 | public static ExecutorService newCachedThreadPool() { |
可以看到最大线程数量是Integer.MAX_VALUE,使用的是SynchronousQueue,因此有任务时不会存在阻塞队列中,会直接创建线程执行。
newFixedThreadPool
1 | public static ExecutorService newFixedThreadPool(int nThreads) { |
定长线程池,使用的是LinkedBlockingQueue阻塞队列,有任务则创建线程,如果达到固定的数量,则存放到阻塞队列中。
newSingleThreadExecutor
创建一个单线程线程池,可以保证线程池中永远有一个线程在工作,保证了任务的顺序性
1 | public static ExecutorService newSingleThreadExecutor() { |
可以看到,调用了ThreadPoolExecutor,只允许一个线程运行。使用方法:
1 | ExecutorService mSingleThreadPool = Executors.newSingleThreadPool(); |
newScheduleThreadPool
1 | public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { |
创建一个大小无限,可以定时执行的线程池。