Java线程池( 三 )


  • ThreadPoolExecutor.AbortPolicy()
抛出RejectedExecutionException异常 。默认策略 。调用者可以捕获抛出的异常 , 进行相应的处理 。
  • ThreadPoolExecutor.CallerRunsPolicy()
不会丢弃任务 , 也不会抛出异常 , 由向线程池提交任务的线程来执行该任务 。
  • ThreadPoolExecutor.DiscardPolicy()
丢弃当前的任务
  • ThreadPoolExecutor.DiscardOldestPolicy()
丢弃最旧的任务(最先提交而没有得到执行的任务) , 并执行当前任务 。
 
ThreadPoolExecutor执行流程如下
Java线程池

文章插图
 
①当新任务提交时 , 如果当前线程池中的线程数小于corePoolSize , 则创建新的线程处理 。
②如果线程池中的线程大于或等于corePoolSize , 且BlockingQueue未满 , 则将新任务加入BlockingQueue 。
③如果BlockingQueue已满 , 且线程池中的线程数小于maximumPoolSize , 则创建新的工作线程来执行任务 。
④如果当前运行的线程大于或等于maximumPoolSize , 将执行饱和策略 。即调用
RejectedExecutionHandler.rejectExecution()方法 。
几种常见的线程池Executors提供了一些静态工厂方法创建的常见线程池 。
  • newFixedThreadPool
创建一个固定长度的线程池 , 每当提交一个任务就创建一个线程 , 直到达到线程池最大长度 , 这时线程池长度不再变化 。如果一个线程异常退出 , 线程池会补充一个新的线程 。
  • newCachedThreadPool
创建一个可缓存的线程池 , 不会对池的长度做限制 。如果线程池长度超过需求 , 它可以灵活地回收空闲的线程;当需求增加时 , 它可以灵活地添加新的线程 。
  • newSingleThreadExecutor
创建一个单线程的executor , 只创建唯一的工作者线程来执行任务 , 如果这个线程异常结束 , 会有一个新的取代它 。
  • newScheduledThreadPool
创建一个定长的线程池 , 支持定时执行任务 。
这几种线程池中 , newFixedThreadPool和newSingleThreadExecutor默认使用无线队列LinkedBlockingQueue 。newCachedThreadPool使用了同步移交队列SynchronousQueue 。newScheduledThreadPool使用了DelayedWorkQueue阻塞队列 。
newCachedThreadPool的corePoolSize为0 , maximumPoolSize为Integer.MAX_VALUE , 其他几种线程池corePoolSize与maximumPoolSize一样大 。
线程池的状态与生命周期线程池有5种状态 , 在ThreadPoolExecutor 源码中有定义 。
  • RUNNING : 线程池最初创建后的初始状态 , 该状态的线程池既能接受新提交的任务  , 又能处理阻塞队列中任务 。
  • SHUTDOWN: 调用shutdown()方法后进入该状态 。该状态的线程池不能接收新提交的任务  , 但是能处理阻塞队列中的任务 。
  • STOP: 调用shutdownNow()方法后进入该状态 。该状态的线程池不接受新提交的任务  , 也不处理在阻塞队列中的任务  , 还会中断正在执行的任务 。
  • TIDYING: 当所有的任务都已终止 , 工作线程数为0的状态 。线程池进入该状态后会调用 terminated() 钩子方法进入TERMINATED 状态 。
  • TERMINATED: 在terminated()钩子方法执行完后进入该状态 。

Java线程池

文章插图
 
调用线程池的shutdown()或者shutdownNow()方法可以关闭线程池 , 遍历线程池中工作线程 , 逐个调用interrupt方法来中断线程 。
Shutdown()方法与shutdownNow()的特点:
Shutdown()方法将线程池的状态设置为SHUTDOWN状态 , 只会中断空闲的工作线程 。
shutdownNow()方法将线程池的状态设置为STOP状态 , 会中断所有工作线程 , 不管工作线程是否空闲 。
调用两者中任何一种方法 , 都会使isShutdown()方法的返回值为true;线程池中所有的任务都关闭后 , isTerminated()方法的返回值为true 。
通常使用shutdown()方法关闭线程池 , 如果不要求任务一定要执行完 , 则可以调用shutdownNow()方法 。


推荐阅读