一.介绍
Java通过Executors提供四种线程池,分别为:
(1)newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
(2)newFixedThreadPool: 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
(3)newScheduledThreadPool :创建一个定长线程池,支持定时及周期性任务执行。
(4)newSingleThreadExecutor: 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
二.基本使用
1.newCachedThreadPool
创建一个可缓存线程池,使用newCachedThreadPool的时候要根据实际任务运行时间情况,因为它可以创建最多Integer.MAX_VALUE个线程,反而会占用系统资源,降低运行效率。这就是为什么官方文档中会说:newCachedThreadPool会大幅度提高大量短暂异步任务的性能了
public static class TestRunable implements Runnable {
int index;
public TestRunable(int i){
this.index=i;
}
@Override
public void run() {
System.out.println("我的线程"+index+":"+this.toString());
}
}
public static void main(String[] args) {
ExecutorService newCachedThreadPool = newCachedThreadPool();
for(int i=0;i<10;i++) {
newCachedThreadPool.execute(new TestRunable(i));
}
}结果:
我的线程0:concurrency.ThreadPoolTest
TestRunable@72f5c249
我的线程2:concurrency.ThreadPoolTestTestRunable@7ad06c3f
我的线程4:concurrency.ThreadPoolTestTestRunable@128abd43
我的线程6:concurrency.ThreadPoolTestTestRunable@5644a213
我的线程8:concurrency.ThreadPoolTestTestRunable@f710c85
2.newFixedThreadPool
public static class TestRunable implements Runnable {
int index;
public TestRunable(int i){
this.index=i;
}
@Override
public void run() {
System.out.println("我的线程"+index+":"+this.toString()+"当前时间:"+new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService newCachedThreadPool = newFixedThreadPool(3);
for(int i=0;i<10;i++) {
newCachedThreadPool.execute(new TestRunable(i));
}
}结果:
我的线程1:concurrency.ThreadPoolTest
TestRunable@e1604df当前时间:Wed Nov 14 16:37:08 CST 2018
我的线程2:concurrency.ThreadPoolTestTestRunable@25fcda8c当前时间:Wed Nov 14 16:37:09 CST 2018
我的线程4:concurrency.ThreadPoolTestTestRunable@5d717931当前时间:Wed Nov 14 16:37:09 CST 2018
我的线程6:concurrency.ThreadPoolTestTestRunable@21c34aeb当前时间:Wed Nov 14 16:37:10 CST 2018
我的线程8:concurrency.ThreadPoolTestTestRunable@21c30e19当前时间:Wed Nov 14 16:37:11 CST 2018
可以发现每次只进入三个进场执行,其他线程等待,当前面的线程执行完毕后后面的线程进入.
3.newScheduledThreadPool
创建固定大小且能够执行定时或周期性任务的线程池
public static class TestRunable implements Runnable {
int index;
public TestRunable(int i){
this.index=i;
}
@Override
public void run() {
System.out.println("我的线程"+index+":"+this.toString()+"当前时间:"+new Date());
}
}
public static void main(String[] args) {
ScheduledExecutorService executorService = newScheduledThreadPool(3);
System.out.println("当前时间:"+new Date());
for(int i=0;i<5;i++) {
executorService.schedule(new TestRunable(i),3, TimeUnit.SECONDS);
}
}结果:
当前时间:Wed Nov 14 17:13:08 CST 2018
我的线程1:concurrency.ThreadPoolTestTestRunable@3272e778当前时间:Wed Nov 14 17:13:11 CST 2018
我的线程3:concurrency.ThreadPoolTestTestRunable@3cb51f46当前时间:Wed Nov 14 17:13:11 CST 2018
我的线程0:concurrency.ThreadPoolTest$TestRunable@b7d228b当前时间:Wed Nov 14 17:13:11 CST 2018
通过结果可看出,先延时3秒后执行线程,除了延迟执行之外和newFixedThreadPool基本相同,可以用来执行定时任务
4.newSingleThreadExecutor
创建单线程的线程池 ,当该单线程在shutdown之前由于失败而终止时,将会有新的线程来代替它执行剩下任务。加入到该线程池里的线程会按顺序执行,一个时刻保证只有一个线程在运行
public static class TestRunable implements Runnable {
int index;
public TestRunable(int i){
this.index=i;
}
@Override
public void run() {
System.out.println("我的线程"+index+":"+this.toString()+"当前时间:"+new Date());
}
}
public static void main(String[] args) {
ExecutorService newSingleThreadExecutor = newSingleThreadExecutor();
System.out.println("当前时间:"+new Date());
for(int i=0;i<10;i++) {
newSingleThreadExecutor.execute(new TestRunable(i));
}
}结果:
当前时间:Wed Nov 14 17:16:07 CST 2018
我的线程0:concurrency.ThreadPoolTestTestRunable@235ec0f4当前时间:Wed Nov 14 17:16:07 CST 2018
我的线程2:concurrency.ThreadPoolTestTestRunable@6263cacf当前时间:Wed Nov 14 17:16:07 CST 2018
我的线程4:concurrency.ThreadPoolTestTestRunable@534bac6b当前时间:Wed Nov 14 17:16:07 CST 2018
我的线程6:concurrency.ThreadPoolTestTestRunable@24c3580当前时间:Wed Nov 14 17:16:07 CST 2018
我的线程8:concurrency.ThreadPoolTestTestRunable@36be2ddf当前时间:Wed Nov 14 17:16:07 CST 2018
可以看出按顺序执行每次只执行一个线程
















