在应用程序中中需要频繁的创建许多生命周期很短的线程,用传统方法的话就会造成大量的资源了浪费,且不可复用和控制回收,就像直接使用jdbc数据连接,而不使用数据库连接池来管理数据库连接一样。
Java在jdk1.5 版本中加入了线程池特性,它负责管理大量的线程的创建销毁等操作。
相关类:java.util.concurrent.Executors(执行器),执行器类拥有大量的静态工厂方法用于创建线程池。
1、线程池实现类:
newCachedThreadPool:通过名称,不难看出这个方法创建出的线程池,具有数量可变,并且在需要的时候会自动创建更多的线程,并且会自动销毁线程。
newFixedThreadPool:此线程池与newCachedThreadPool构建出的线程池的主要区别是,线程池在数量上固定,如果任务数量达到上限的话,就会将多余任务加入任务队列,等线程池空出线程时即可执行,这种线程池并不会销毁空闲线程。
newSingleThreadExecutor:此方法创建出的线程池相较于其他两个线程较为特殊,此方法创建出的线程数量仅仅为1,也就是说所有除了正在执行的任务外,其余任务均在任务队列中,当线程中的任务执行完毕后,任务队列的第一个任务进入线程开始执行。
newScheduledThreadPool与newSingleThreadScheduledExecutor:这两个方法创建出的线程池是用于预定执行的线程池,他们可以用于在初始化后延迟执行,或周期性的执行,两种线程池大体相同,唯一的区别就是可同时执行的线程数量。
2、线程池使用步骤:
(1)调用执行器类(Executors)的静态方法来创建线程池
(2)调用线程池的submit方法提交Runnable或Callable对象
(3)调用shutdown关闭入口,让线程池不能再提交任务,之前的任务仍会执行完成
3、代码操作示例:
//创建线程池对象
ExecutorService service = Executors.newCachedThreadPool();
//创建一个用于递增输出i值的runnable对象
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
}
};
//调用线程池的submit方法传入runnable(传入的runnable将会自动执行)
service.submit(runnable);
//调用shutdown方法关闭入口
service.shutdown();
// 用来关闭线程池入口以及终止所有正在执行的任务
service.shutdownNow();
PS: 如果希望直接停止线程池的一切任务是无法通过shutdown来操作的,因为shutdown仅仅是关闭了入口,但是已经加入的任务还是会继续执行的,这时我们可以调用线程池的shutdownNow方法来操作,shutdownNow的作用是用来关闭线程池的入口并且会尝试终止所有当前线程池内的任务。
4、获取线程执行结果或查看线程状态:
service的submit方法会返回一个Future<?>类型的对象,该对象用于在加入线程池以后能够对此任务进行取消,查看状态等操作,如果说在加入线程池以后有可能会取消此任务的话就需要,在submit的时候就需要保存好Future对象。
//保存Future<?>
Future<?> run2 = service.submit(runnable);
//用于查看是否已经执行完毕,返回类型为boolean
System.out.println(run2.isDone());
//取消任务,如果需要中断的话参数为true
run2.cancel(true);