引用:
http://blog.csdn.net/evankaka/article/details/51489322
一、概述
1、主线程的执行与线程池里的线程互不影响,有可能主线程结束了,但是线程池里的线程还在运行
2、放入线程池的线程并不一定会按其放入的先后而顺序执行
3:线程池关系图
二、Executors的API介绍
Java类库提供了许多Executors的静态方法来创建一个线程池
a、newFixedThreadPool
创建一个固定长度的线程池.
fixed池中的线程不会过期(idle是0)
b、newCachedThreadPool
创建一个可缓存的线程池.
如果当前线程池的规模超出了处理需求,将回收空的线程;
当需求增加时,会增加线程数量;线程池规模无限制。
能reuse的线程,必须是idle(空闲) timeout内的池中线程,缺省timeout是60s,超过这个idle时长,线程实例将被终止及移出线程池。
c、newSingleThreadExecutor
创建一个单线程的Executor.
任意时间池中只能有一个线程,线程不会过期(idle是0)
作用:保证线程的执行顺序,用一个线程按顺序执行等待队列中的多个任务
d、newScheduledThreadPool
创建一个固定长度的线程池,而且以延迟或者定时的方式来执行,类似Timer;
- scheduleAtFixedRate()方法:按指定频率周期执行某个任务
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
command:执行线程 initialDelay:初始化延时 period:两次开始执行最小间隔时间 unit:计时单位
间隔指的是连续两次任务开始执行的间隔。对于scheduleAtFixedRate方法,当执行任务的时间大于我们指定的间隔时间时,它并不会在指定间隔时开辟一个新的线程并发执行这个任务。而是等待该线程执行完毕。
- scheduleWithFixedDelay()方法:按指定频率间隔执行某个任务
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
command:执行线程 initialDelay:初始化延时 period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)unit:计时单位
- scheduleAtFixedRate和scheduleWithFixedDelay对比
两者都是一个任务只会开启一个线程,上一个任务结束前下一个任务不会开始(不管线程池设的多大)
区别是FixedRate指定两次任务的开启时间间隔,FixedDelay指定两次任务的执行时间间隔
三、线程池一些常用方法
submit
Submit和execuie都可以将线程放到线程池中.区别是,submit用于执行需要返回值的子任务(Callable任务).
execute
表示往线程池添加线程,有可能会立即运行,也有可能不会。无法预知线程何时开始,何时线束。
shutdown
如果调用这个方法,一方面,表明当前线程池已不再接收新添加的线程,新添加的线程会被拒绝执行。另一方面,表明当所有线程执行完毕时,回收线程池的资源。shutdown()不会马上关闭线程池!
shutdownNow
不管当前有没有线程在执行,马上关闭线程池!这个方法要小心使用,要不可能会引起系统数据异常!
四、任务拒绝策略
① ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
② ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
③ ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
④ ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
五、总结
ThreadPoolExecutor中,包含了一个任务缓存队列和若干个执行线程,任务缓存队列是一个大小固定的缓冲区队列,用来缓存待执行的任务,执行线程用来处理待执行的任务。每个待执行的任务,都必须实现Runnable接口,执行线程调用其run()方法,完成相应任务。
ThreadPoolExecutor对象初始化时,不创建任何执行线程,当有新任务进来时,才会创建执行线程。
构造ThreadPoolExecutor对象时,需要配置该对象的核心线程池大小和最大线程池大小:
当目前执行线程的总数小于核心线程大小时,所有新加入的任务,都在新线程中处理
当目前执行线程的总数大于或等于核心线程时,所有新加入的任务,都放入任务缓存队列中
当目前执行线程的总数大于或等于核心线程,并且缓存队列已满,同时此时线程总数小于线程池的最大大小,那么创建新线程,加入线程池中,协助处理新的任务。
当所有线程都在执行,线程池大小已经达到上限,并且缓存队列已满时,就rejectHandler拒绝新的任务