为什么需要线程池
1. 一个线程完成一项任务所需时间为:T1创建线程时间,T2在线程中执行任务的时间,T3销毁线程时间。
2. 线程池技术正是关注如何缩短或调整T1、T3时间的技术,从而提高程序的性能。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。
3. 线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目。
4. 系统启动一个新线程的成本是比较高的,因为涉及与操作系统的交互,在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,优先考虑使用线程池。
5. 线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象传给线程池,线程池就会启动一条线程来执行该对象的run方法,当run方法执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的Run方法。
6. JDK1.5以前,开发者必须手动实现自己的线程池,JDK1.5开始,Java内建支持线程池 ThreadPool
ExecutorService:线程池的接口
2. Executors:创建各种线程池的工具类
3. newSingleThreadExecutor()
创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
4. newFixedThreadPool(int n)
创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
5. newCachedThreadPool()
创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
//new Thread(new Task3()).start(); //常规的创建线程方式--
//1.创建单个线程池的方式
//ExecutorService service = Executors.newSingleThreadExecutor();
//2.创建固定线程池个数的方式
//ExecutorService service = Executors.newFixedThreadPool(2);
//3.创建可缓存的线程池--根据任务数,灵活控制线程对象个数
ExecutorService service = Executors.newCachedThreadPool();
service.submit(new Task3()); //提交一个任务
service.submit(new Task3());
service.submit(new Task3()); //谁先执行完谁继续执行
service.shutdown();//关闭线程池