FixedThreadPool
核心线程数和最大线程数是一样的,特点就是初始阶段需要从 0 开始增加外,之后的线程数量就是固定的。
CachedThreadPool
线程数是几乎可以无限增加的,当线程闲置时可以对线程进行回收。区别就是用于存储提交任务的队列(SynchronousQueue)容量为0,实际不存储任何任务,它只负责对任务进行中转和传递,所以效率比较高。
ScheduledThreadPool
它支持定时或周期性执行任务
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);// 延迟10秒后执行一次任务service.schedule(new Task(), 10, TimeUnit.SECONDS);// 每10秒执行一次任务,执行20次service.scheduleAtFixedRate(new Task(), 10, 20, TimeUnit.SECONDS);// 每执行一次任务过10秒后再次执行,执行20次service.scheduleWithFixedDelay(new Task(), 10, 20, TimeUnit.SECONDS);
SingleThreadExecutor
只会有一个线程去执行任务,如果线程在执行任务的过程中发生异常,线程池会重新创建一个线程来执行后续的任务
SingleThreadScheduledExecutor
和ScheduledThreadPool非常相似,只是把核心线程数设置成了1
ForkJoinPool
主要用法和之前的线程池是相同的,但是 ForkJoinPool 线程池有两点非常大的不同之处:
ForkJoinPool可以将一个任务分裂成多个任务最后汇总
除了公共队列线程池中的每个子线程都有自己独立的的任务队列(WorkQueue)还有一个对应的双端队列
双端队列(steal):其他空闲的子线程会去获取(work-stealing)其他繁忙线程双端队列中的任务
例子:打斐波那契数列
public static void main(String[] args) throws ExecutionException, InterruptedException {ForkJoinPool forkJoinPool = new ForkJoinPool();for (int i = 0; i < 10; i++) {ForkJoinTask<Integer> task = forkJoinPool.submit(new Fibonacci(i));System.out.println(task.get());}}public class Fibonacci extends RecursiveTask<Integer> {int n;public Fibonacci(int n) {this.n = n;}@Overrideprotected Integer compute() {if (n <= 1) {return n;}Fibonacci f1 = new Fibonacci(n - 1);f1.fork();Fibonacci f2 = new Fibonacci(n - 2);f2.fork();return f1.join() + f2.join();}}
