在许多应用中须要频繁的建立许多生命周期很短的线程,若是用传统方法的话就会形成大量的资源了浪费,java的设计者们考虑到了这点在java中加入了线程池这个特性,它负责管理大量的线程的建立销毁等操做。java
首先咱们须要了解一个类:java.util.concurrent.Executors(执行器)api
执行器类拥有大量的静态工厂方法用于建立线程池ide
方法 | 描述 |
newCachedThreadPool | 必要时建立线程,处于空闲状态的线程将被保留60秒 |
newFixedThreadPool | 拥有固定数量的线程,而且不会自动销毁空闲状态的线程 |
newSingleThreadExecutor | 该线程池仅有一个线程,会顺序执行任务队列 |
newScheduledThreadPool | 用于预定执行任务的固定线程池 |
newSingleThreadScheduledExecutor | 用于预定执行任务的单线程池 |
下面咱们来详细了解下这些线程池。spa
newCachedThreadPool:经过名称,不难看出这个方法建立出的线程池,具备数量可变,而且在须要的时候会自动建立更多的线程,而且会自动销毁线程。线程
newFixedThreadPool:此线程池与newCachedThreadPool构建出的线程池的主要区别是,线程池在数量上固定,如果任务数量达到上限的话,就会将多余任务加入任务队列,等线程池空出线程时便可执行,这种线程池并不会销毁空闲线程。 设计
newSingleThreadExecutor:此方法建立出的线程池相较于其余两个线程较为特殊,此方法建立出的线程数量仅仅为1,也就是说全部除了正在执行的任务外,其他任务均在任务队列中,当线程中的任务执行完毕后,任务队列的第一个任务进入线程开始执行。code
newScheduledThreadPool与 newSingleThreadScheduledExecutor:这两个方法建立出的线程池是用于预约执行的线程池,他们能够用于在初始化后延迟执行,或周期性的执行,两种线程池大致相同,惟一的区别就是可同时执行的线程数量。对象
当挑选完的线程池后就须要建立以及使用线程池:生命周期
大概步骤为如下3步:队列
(1)调用执行器类(Executors)的静态方法来建立线程池
(2)调用线程池的submit方法提交Runnable或Callable对象
(3)当不须要添加更多的任务时,调用shutdown关闭入口
下面经过代码来逐步操做:
//建立线程池对象 ExecutorService service = Executors.newCachedThreadPool(); //建立一个用于递增输出i值的runnable对象 Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0; i < 400; i++) { System.out.println(i); } } }; //调用线程池的submit方法传入runnable(传入的runnable将会自动执行) service.submit(runnable); service.submit(runnable); //当不须要传入更多的任务时调用shutdown方法来关闭入口 service.shutdown();
须要注意的是若是但愿直接中止线程池的一切任务是没法经过shutdown来操做的,由于shutdown仅仅是关闭了入口,可是已经加入的任务仍是会继续执行的,这时咱们能够调用线程池的shutdownNow方法来操做,shutdownNow的做用是用来关闭线程池的入口而且会尝试终止全部当前线程池内的任务。
//用来关闭线程池入口以及终止全部正在执行的任务 service.shutdownNow();
service的submit方法会返回一个Future<?>类型的对象,然而这是一个怎样的类型呢?让咱们来看一下api中的方法摘要:
从方法摘要中能够看出该对象用于在加入线程池之后可以对此任务进行取消,查看状态等操做,若是说在加入线程池之后有可能会取消此任务的话就须要,在submit的时候就须要保存好Future对象。
//保存Future<?> Future<?> run2 = service.submit(runnable); //用于查看是否已经执行完毕,返回类型为boolean System.out.println(run2.isDone()); //取消任务,若是须要中断的话参数为true run2.cancel(true);
关于线程池的简单操做大概就有这些.