目录
原理
好处
创建线程池
构造方法
参数详解
int corePoolSize
int maximumPoolSize
long keepAliveTime
TimeUnit unit
BlockingQueue workQueue
ThreadFactory threadFactory
RejectedExecutionHandler hanler
执行任务
execute()
submit()
并发操作
关闭线程池
shutdown()
shutdownNow()
线程池就是一个存放已经创建好的线程的池子,当有任务提交给线程池执行时,线程池中的某个线程会主动执行该任务。如果线程池中的线程数量不够应付数量众多的任务时,需要自动扩充新的线程到线程池中,数量是有限的。当任务比较少的时候,线程池中的线程能够自动回收,释放资源。
降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行。
提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
通过java.util.concurrent.ThreadPoolExecutor来创建一个线程池。
//五个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
//六个参数的构造函数-1
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
ThreadFactory threadFactory)
//六个参数的构造函数-2
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
RejectedExecutionHandler handler)
//七个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
该线程池中核心线程的最大数量,即默认情况下一直会存活在线程池中,即使处于闲置状态。如果当前线程总数小于corePoolSize,新建的线程是核心线程,否则是非核心线程。
该线程池中线程总数最大值。
表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0。
参数keepAliveTime的时间单位
TimeUnit是一个枚举类型,其包括:
NANOSECONDS : 1微毫秒 = 1微秒 / 1000
MICROSECONDS : 1微秒 = 1毫秒 / 1000
MILLISECONDS : 1毫秒 = 1秒 /1000
SECONDS : 秒
MINUTES : 分
HOURS : 小时
DAYS : 天
该线程池中的任务队列,用来存储等待执行的任务。
线程工厂,主要用来创建线程,一般用不上。
表示当拒绝处理任务时的策略,有以下四种取值:
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
这个方法是顶层接口Executor中声明的方法,在ThreadPoolExecutor类中进行了具体实现,参数是Runnable,通过这个方法可以向线程池提交一个任务,交由线程池去执行。
Submit是在接口ExecutorService中声明的方法,在ThreadPoolExecutor类的抽象父类AbstractExecutorService中进行了具体实现。这个方法也是用来向线程池提交任务的,参数是Runnable,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果。
可以和CountDownLatch配合使用:
1、主线程使用await() 阻塞住,直到所有子线程都执行完毕了,才会继续向下执行。
2、所有子线程共享同一个 CountDownLatch变量,需要执行的线程总数。
3、所有子线程的finally块中,必须要countDown() ,确保 "无论 正确、异常 都会countDown",否则主线程会由于"某一个 子任务 没有countDown过,就执行结束了,导致CountDownLatch最终无法被countDown 到 0 ,而被永远挂住。
不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。
立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。