学习Java的时候并没有深入的了解ExecutorService,但是在做Android项目开发的时候使用到ExecutorService线程池。开始并不怎么理解,在网上查阅一下资料,并观看了Java API文档理解了ExecutorService的使用,特写出此博客方便自己和大家阅读,有理解错误的地方希望阅读者可以指出,谢谢!
创建ExecutorService对象
创建ExecutorService对象常用的方法有以下四种
// 创建可以容纳3个线程的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
// 线程池的大小会根据执行的任务数动态分配
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// 创建单个线程的线程池,如果当前线程在执行任务时突然中断,则会创建一个新的线程替代它继续执行任务
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
// 效果类似于Timer定时器
ScheduledExecutorService scheduledThreadPool = Executors
.newScheduledThreadPool(3);
我在下面写一个示例方便大家的理解:
示例:
public class Example {
private static void run(ExecutorService threadPool) {
for (int i = 0; i < 4; i++) {
final int threadId = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 4; i++) {
try {
Thread.sleep(30);// 为了测试出效果,让每次任务执行都需要一定时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第" + threadId + "次线程的第" + i + "次执行");
}
}
});
}
threadPool.shutdown();//养成良好的编程习惯,关闭线程池
}
public static void main(String[] args) {
// 创建可以容纳3个线程的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
// 线程池的大小会根据执行的任务数动态分配
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// 创建单个线程的线程池,如果当前线程在执行任务时突然中断,则会创建一个新的线程替代它继续执行任务
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
// 效果类似于Timer定时器
ScheduledExecutorService scheduledThreadPool = Executors
.newScheduledThreadPool(3);
run(fixedThreadPool);
// run(cachedThreadPool);
// run(singleThreadPool);
// run(scheduledThreadPool);
}
}
FixedThreadPool
在FixedThreadPool中,有一个固定大小的池。如果当前需要执行的任务超过池大小,那么多出的任务处于等待状态,直到有空闲下来的线程执行任务,如果当前需要执行的任务小于池大小,空闲的线程也不会去销毁。
执行结果:
第0次线程的第0次执行
第2次线程的第0次执行
第1次线程的第0次执行
第1次线程的第1次执行
第2次线程的第1次执行
第0次线程的第1次执行
第2次线程的第2次执行
第0次线程的第2次执行
第1次线程的第2次执行
第1次线程的第3次执行
第0次线程的第3次执行
第2次线程的第3次执行
第3次线程的第0次执行
第3次线程的第1次执行
第3次线程的第2次执行
第3次线程的第3次执行
CachedThreadPool
CachedThreadPool会创建一个缓存区,将初始化的线程缓存起来。会终止并且从缓存中移除已有60秒未被使用的线程。如果线程有可用的,就使用之前创建好的线程,
如果线程没有可用的,就新创建线程。注意,放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止。
执行结果:
第3次线程的第0次执行
第2次线程的第0次执行
第1次线程的第0次执行
第0次线程的第0次执行
第0次线程的第1次执行
第1次线程的第1次执行
第3次线程的第1次执行
第2次线程的第1次执行
第3次线程的第2次执行
第2次线程的第2次执行
第0次线程的第2次执行
第1次线程的第2次执行
第2次线程的第3次执行
第3次线程的第3次执行
第0次线程的第3次执行
第1次线程的第3次执行
SingleThreadExecutor
SingleThreadExecutor得到的是一个单个的线程,这个线程会保证你的任务执行完成。如果当前线程意外终止,会创建一个新线程继续执行任务,这和我们直接创建线程不同,也和newFixedThreadPool(1)不同。
执行结果:
第0次线程的第0次执行
第0次线程的第1次执行
第0次线程的第2次执行
第0次线程的第3次执行
第1次线程的第0次执行
第1次线程的第1次执行
第1次线程的第2次执行
第1次线程的第3次执行
第2次线程的第0次执行
第2次线程的第1次执行
第2次线程的第2次执行
第2次线程的第3次执行
第3次线程的第0次执行
第3次线程的第1次执行
第3次线程的第2次执行
第3次线程的第3次执行
ScheduledThreadPool
ScheduledThreadPool是一个固定大小的线程池,与FixedThreadPool类似,执行的任务是定时执行
执行结果:
第1次线程的第0次执行
第2次线程的第0次执行
第0次线程的第0次执行
第2次线程的第1次执行
第1次线程的第1次执行
第0次线程的第1次执行
第0次线程的第2次执行
第2次线程的第2次执行
第1次线程的第2次执行
第1次线程的第3次执行
第2次线程的第3次执行
第0次线程的第3次执行
第3次线程的第0次执行
第3次线程的第1次执行
第3次线程的第2次执行
第3次线程的第3次执行
看完示例大家应该更加深刻的理解了ExecutorService的机制了吧!如果博客中解释错误或者不清晰,请读者留言指教。谢谢!