Java并发编程:线程池的使用
整理自:博客园-海子-http://www.cnblogs.com/dolphin0520/p/3932921.html
1、什么是线程池,为什么要使用线程池:
1.1、线程池是线程的集合,里面的线程可以重复使用:java在java.util.concurrent下提供了一个Executor接口及其实现,用于创建管理线程池;线程池是指在初始化一个多线程应用时创建一个线程集合,再需要执行新的任务时,重复使用这些线程,而不是去创建新线程。
1.2、(1)缩短线程的创建和销毁时间,提高程序的性能;
(2)根据系统的承受能力,调整线程池中工作线程的数目,防止开销过大造成宕机。
1.3、常用的几种线程池:java doc不建议我么直接使用ThreadPoolExecutor创建线程池,而是使用Executors的静态方法创建;
(1):Executors.newCachedThreadPool(); 可缓存线程池,可根据需要创建新线程,终止超过60秒空闲的线程。
(2):Executors.newSingleThreadExecutor(); 只有一个单线程,串行执行所有任务。
(3):Executors.newFixedThreadPool(
int
):固定线程数线程池,达到固定数量后不新建也不消除。
2、Java中的ThreadPoolExecutor类
2.1、主要参数:corePoolSize:核心池的大小;maximumPoolSize:最大线程数;keepAliveTime:无任务时线程保持多久会终止;unit:KeepAliveTime的时间单位;workQueue:阻塞队列,存储等待执行的任务;threadFactory线程工厂用来创建线程;hander:拒绝处理任务时的策略; 2.2、继承关系:ThreadPoolExecutor继承自AbstractExecutorService实现了ExecutorService接口继承了Executor接口; 2.3、ThreadPoolExecutor中的主要方法:
execute():提交任务
submit():提交任务并返回结果Future;
shutdown()shutdownNow():关闭线程池;
2.4、线程池的状态:
Running(创建时运行)->ShutDown(调用shutdown)/Stop(调用ShutDownNow状态)->Terminated(上一状态,所有线程已销毁,缓存队列已经清空);
2.5、任务的执行:
【1】线程池有线程(<corePoolSize)空闲,来任务给空闲线程;
【2】CorePoolSize已满,尝试将任务进入等待队列,若不成功(workQueue已满)尝试新建线程去执行该任务;
【3】当前线程池数量达到maximumPoolSize,再来的任务采取拒绝策略(hander)处理任务;
【4】线程数量超过maximumPoolSize时,若空闲线程的空闲时间超过了keepAliveTime,线程被终止,知道线程数量不大于CorePoolSize;如果允许核心线程设置KeepAliveTime,那么核心线程空闲一定时间后也会被终止。
2.6、任务缓存队列workQueue及其排队策略:
workQueue用来存放等待执行的任务,类型为BlockingQueue<Runnable>通常取一下三种类型:
(1):ArrayBlockingQueue:基于数组的,先进先出,需要指名大小;
(2):LinkedBlockingQueue:基于链表的先进先出队列,默认大小Integer.MAX_VALUE
(3):synchronousQueue:不保存任务,直接开启新线程去执行任务。
2.7、任务拒绝策略:线程池任务缓存队列workQueue以满,且线程池内线程数目达到maximumPoolSize:
(1):ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
(2):ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
(3):ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
(4):ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
2.8、关闭:shutdown()等待所有任务结束,且不接受新任务;shutdownNow():立即关闭,尝试打断正在执行的任务,清空缓存队列。
2.9、线程池容量动态调整:setCorePoolSize()和setMaximumPoolSize();
3、:java中ThreadPoolExecutor的使用实例;
public class Test { public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(5)); for(int i=0;i<15;i++){ MyTask myTask = new MyTask(i); executor.execute(myTask); System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+ executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount()); } executor.shutdown(); } } class MyTask implements Runnable { private int taskNum; public MyTask(int num) { this.taskNum = num; } @Override public void run() { System.out.println("正在执行task "+taskNum); try { Thread.currentThread().sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("task "+taskNum+"执行完毕"); } } 结果: 正在执行task 0 线程池中线程数目:1,队列中等待执行的任务数目:0,已执行玩别的任务数目:0 线程池中线程数目:2,队列中等待执行的任务数目:0,已执行玩别的任务数目:0 正在执行task 1 线程池中线程数目:3,队列中等待执行的任务数目:0,已执行玩别的任务数目:0 正在执行task 2 线程池中线程数目:......
4、java.util.concurrent.ThreadPoolExecutor的继承关系