Java通过Executors(jdk1.5并发包)提供四种线程池,分别为:
- newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任
务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
四种构建线程池的区别及特点:
- newCachedThreadPool
特点:newCachedThreadPool创建一个可缓存线程池,如果当前线程池的长度超过了处理的需要时,它可以灵活的回收空闲的线程,当需要增加时,它可以灵活的添加新的线程,而不会对池的长度作任何限制
缺点:它虽然可以无限的新建线程,但是容易造成堆外内存溢出,因为它的最大值是在初始化的时候设置为Integer.MAX_VALUE,一般来说机器都没那么大内存给它不断使用。当然知道可能出问题的点,就可以去重写一个方法限制一下这个最大值
总结:线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程
代码实列:package com.lijie; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestNewCachedThreadPool { public static void main(String[] args) { // 创建无限大小线程池,由jvm自动回收 ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int temp = i; newCachedThreadPool.execute(new Runnable() { public void run() { try { Thread.sleep(100); } catch (Exception e) { } System.out.println(Thread.currentThread().getName() + ",i==" + temp); } }); } } }
-
newFixedThreadPool
特点:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。定长线程池的大小最好根据系统资源进行设置。
缺点:线程数量是固定的,但是阻塞队列是无界队列。如果有很多请求积压,阻塞队列越来越长,容易导致OOM(超出内存空间)
总结:请求的挤压一定要和分配的线程池大小匹配,定线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
代码实例:package com.lijie; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestNewFixedThreadPool { public static void main(String[] args) { ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int temp = i; newFixedThreadPool.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + ",i==" + temp); } }); } } }
-
newScheduledThreadPool
特点:创建一个固定长度的线程池,而且支持定时的以及周期性的任务执行,类似于
Timer(Timer是Java的一个定时器类)
缺点:由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务(比如:一个任务出错,以后的任务都无法继续)。
代码示例:package com.lijie; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class TestNewScheduledThreadPool { public static void main(String[] args) { //定义线程池大小为3 ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3); for (int i = 0; i < 10; i++) { final int temp = i; newScheduledThreadPool.schedule(new Runnable() { public void run() { System.out.println("i:" + temp); } }, 3, TimeUnit.SECONDS);//这里表示延迟3秒执行。 } } }
-
newSingleThreadExecutor
特点:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它,他必须保证前一项任务执行完毕才能执行后一项。保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
缺点:缺点的话,很明显,他是单线程的,高并发业务下有点无力
总结:保证所有任务按照指定顺序执行的,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它
代码实例:package com.lijie; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestNewSingleThreadExecutor { public static void main(String[] args) { ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index = i; newSingleThreadExecutor.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + " index:" + index); try { Thread.sleep(200); } catch (Exception e) { } } }); } } }