1、为何要引入线程池
传统的多线程任务的执行策略是“即时创建,即时销毁”。这种策略存在明显的弊端:当需要线程的执行任务时间较短,而执行次数比较频繁的时候,系统就处于不停的创建线程,销毁线程的状态。
2、线程池有什么优点
而线程池能够有效减少创建的线程个数。通常线程池所允许的并发线程是有上限的,如果同时需要并发的线程数超过上限,那么一部分线程将会等待。
线程池的出现正是着眼于减少线程本身带来的开销(线程创建和销毁所带来的时间消耗)。
3、线程池常用的用法
思路:
线程池采用预创建的技术,在应用程序启动之后,立即创建一定数目的线程,放入空闲队列中。
这些线程都处于阻塞(挂起)状态,不消耗CPU资源,只占用较小的内存空间。
当任务到来后,缓冲池选择一个空闲线程,把任务传入此线程中运行。
当线程池中的线程都在处理任务时,线程池自动创建一定数量的新线程,用于处理更多的任务。
在任务执行完毕后线程不退出,而是继续保持在线程中(阻塞或挂起)等待下一次的任务。
当系统比较空闲时,大部分线程处于暂停状态,线程池自动销毁一部分线程,回收系统资源。
1)newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,如果没有可回收线程,则创建新线程。
优点:
- 创建线程的数量没有限制(最大为Integer.MAX_VALUE)
- 如果线程池中没有可执行任务(工作线程空闲了指定的时间,比如1分钟),则该工作线程自动终止。终止后,如果提交了新的任务,则线程池重新创建一个工作线程。
- 要注意控制线程的数量,不可过多
代码实现:
ExecutorService cachedThreadPool=Executors.newCachedThreadPool();
for(int i=0;i<20;i++){
Thread.sleep(i*1000);
cachedThreadPool.execute(
new Runnable(){
public void run(){
System.out.println(i);
}
}
);
}
2)newFixedThreadPool
创建一个指定工作线程数量的线程池。每提交一次任务就创建一个工作线程,如果工作线程数量达到线程池的最大数,则将提交的任务存入线程池队列中。
优点:
- 它是一个典型且优秀的线程池,提高程序效率和节省创建线程时所耗的时间开销
缺点:
- 当线程池中没有可执行任务时,它不会释放工作线程,还会占用一定是系统资源。
代码实现:
ExecutorService fixedThreadPool=Executors.newFixedThreadPool(3);
for(int i=0;i<15;i++){
fixedThreadPool.execute(new Runnable(){
public void run(){
System.out.println(i);
Thread.sleep(2000);
}
}
);
线程池大小设置为3,每个任务输出i后,延迟3秒,所以每3秒输出一个字符。
3)newSingleThreadPool
创建一个单线程的Executo。这个线程池中只有一个工作线程来执行任务,可以保证所有的任务按照指定顺序来执行。如果该线程出现异常,会新建另一个线程取而代之。
优点:保证顺序地执行各个任务,并且在任意时间不会有多个线程是活动的。
代码实现:
ExecutorService singleThreadPool=Executors.newSingleThreadExecutor();
for(int i=0;i<20;i++){
singleThreadPool.execute(
new Runnable(){
public void run(){
System.out.println(i);
Thread.sleep(2000);
}
}
);
}
4)newScheduleThreadPool
创建一个定长的线程池,同时支持定时任务、定时及周期性任务。
代码实现一个 延时任务:
ExecutorService scheduleThreadPool=Executors.newScheduleThreadPool(5);
for(int i=0;i<20;i++){
scheduleThreadPool.scheduleAtFixedRate(
new Runnable(){
public void run(){
System.out.println(“延迟3秒钟”);
}
},3,TimeUnit.SECONDS
);
代码实现一个 定时同时延迟执行:
ExecutorService scheduleThreadPool=Executors.newScheduleThreadPool(5);
for(int i=0;i<20;i++){
schduleThreadPool.execute(
new Runnable(){
public void run(){
System.out.println("延迟1s,每次执行时间3秒钟");
}
},1,3,TimeUnit.SECONDS
);