jdk-Executor线程池源码学习
创始人
2025-05-28 04:16:21
0

什么是线程?

一个应用程序为一个进程(也有多个的),一个进程拥有至少1个线程,线程是这个进程所私有的,当进程结束时,线程会随着结束。如下图

97dde6ff717e5faab723e9da73b0931c.png

当然更有一些内存相关的,这里不再过多深入,仅了解基础,不懂的同学自行搜索。

线程有哪些生命状态,怎么切换的?

NEW,新建

RUNNABLE,运行

BLOCKED,阻塞

WAITING,等待

TIMED_WAITING,超时等待

TERMINATED,终结

a77538e0e2c1ac0c26f5152bb176ac3a.png

注意:java原生包不支持协程,需要支持可以引入第三方的quasar

java线程池有哪些?

线程池的主要作用是用来管理线程的一个容器,通过这个可以减少线程被无限制的创建和释放,导致系统资源无法很好管控,通过线程池可以通过分配、调优以及监控。

FixedThreadPool:固定大小的线程池,创建时指定线程数量,任务队列为无界队列。

  1. CachedThreadPool:缓存线程池,线程数量不固定,会根据需要自动创建新线程,空闲线程会被保留60秒,任务队列为SynchronousQueue。

  2. ScheduledThreadPool:定时器线程池,支持延时执行和定时周期执行任务。

  3. SingleThreadExecutor:单线程线程池,只有一个线程执行任务,任务队列为无界队列。

  4. WorkStealingPool:工作窃取线程池,每个线程都有自己的任务队列,线程可以从其他线程的任务队列中窃取任务执行。

线程池的基本使用

package com.executor;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @author: csh* @Date: 2023/3/6 23:02* @Description:固定大小的线程池,线程数一旦达到最大值,新任务就会在等待队列中等待。适用于预先知道任务数量的情况。*/
public class FixedThreadPoolStudy {public static void main(String[] args) {// 创建一个包含5个线程的线程池ExecutorService executorService = Executors.newFixedThreadPool(5);// 提交10个任务for (int i = 1; i <= 10; i++) {executorService.execute(new Task(i));}// 关闭线程池executorService.shutdown();}static class Task implements Runnable {private int taskId;public Task(int taskId) {this.taskId = taskId;}@Overridepublic void run() {System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());try {// 模拟任务执行的耗时Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());}}
}

运行结果

任务1开始执行,当前线程名为pool-1-thread-1
任务2开始执行,当前线程名为pool-1-thread-2
任务3开始执行,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-4
任务5开始执行,当前线程名为pool-1-thread-5
任务3执行完毕,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务7开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-2
任务8开始执行,当前线程名为pool-1-thread-2
任务4执行完毕,当前线程名为pool-1-thread-4
任务9开始执行,当前线程名为pool-1-thread-4
任务5执行完毕,当前线程名为pool-1-thread-5
任务10开始执行,当前线程名为pool-1-thread-5
任务6开始执行,当前线程名为pool-1-thread-3
任务9执行完毕,当前线程名为pool-1-thread-4
任务10执行完毕,当前线程名为pool-1-thread-5
任务8执行完毕,当前线程名为pool-1-thread-2
任务7执行完毕,当前线程名为pool-1-thread-1
任务6执行完毕,当前线程名为pool-1-thread-3
package com.executor;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @author: csh* @Date: 2023/3/6 23:02* @Description:固定大小的线程池,线程数一旦达到最大值,新任务就会在等待队列中等待。适用于预先知道任务数量的情况。*/
public class FixedThreadPoolStudy {public static void main(String[] args) {// 创建一个包含5个线程的线程池ExecutorService executorService = Executors.newFixedThreadPool(5);// 提交10个任务for (int i = 1; i <= 10; i++) {executorService.execute(new Task(i));}// 关闭线程池executorService.shutdown();}static class Task implements Runnable {private int taskId;public Task(int taskId) {this.taskId = taskId;}@Overridepublic void run() {System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());try {// 模拟任务执行的耗时Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());}}
}

结果

任务1开始执行,当前线程名为pool-1-thread-1
任务2开始执行,当前线程名为pool-1-thread-2
任务3开始执行,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-4
任务5开始执行,当前线程名为pool-1-thread-5
任务3执行完毕,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务7开始执行,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-3
任务2执行完毕,当前线程名为pool-1-thread-2
任务8开始执行,当前线程名为pool-1-thread-2
任务4执行完毕,当前线程名为pool-1-thread-4
任务5执行完毕,当前线程名为pool-1-thread-5
任务9开始执行,当前线程名为pool-1-thread-4
任务10开始执行,当前线程名为pool-1-thread-5
任务6执行完毕,当前线程名为pool-1-thread-3
任务8执行完毕,当前线程名为pool-1-thread-2
任务9执行完毕,当前线程名为pool-1-thread-4
任务7执行完毕,当前线程名为pool-1-thread-1
任务10执行完毕,当前线程名为pool-1-thread-5
package com.executor;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**** 功能描述: SingleThreadExecutor是一个只有一个线程的线程池,用于顺序执行任务。** @param:* @return: * @auther: csh* @date: 2023/3/6 11:09 下午*/
public class SingleThreadExecutorStudy {public static void main(String[] args) {// 创建一个只有一个线程的线程池ExecutorService executorService = Executors.newSingleThreadExecutor();// 提交10个任务for (int i = 1; i <= 10; i++) {executorService.execute(new Task(i));}// 关闭线程池executorService.shutdown();}static class Task implements Runnable {private int taskId;public Task(int taskId) {this.taskId = taskId;}@Overridepublic void run() {System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());try {// 模拟任务执行的耗时Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());}}
}

结果 (可以看出下面只有一个线程在跑)

任务1开始执行,当前线程名为pool-1-thread-1
任务1执行完毕,当前线程名为pool-1-thread-1
任务2开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-1
任务3开始执行,当前线程名为pool-1-thread-1
任务3执行完毕,当前线程名为pool-1-thread-1
任务4开始执行,当前线程名为pool-1-thread-1
任务4执行完毕,当前线程名为pool-1-thread-1
任务5开始执行,当前线程名为pool-1-thread-1
任务5执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务6执行完毕,当前线程名为pool-1-thread-1
任务7开始执行,当前线程名为pool-1-thread-1
任务7执行完毕,当前线程名为pool-1-thread-1
任务8开始执行,当前线程名为pool-1-thread-1
任务8执行完毕,当前线程名为pool-1-thread-1
任务9开始执行,当前线程名为pool-1-thread-1
任务9执行完毕,当前线程名为pool-1-thread-1
任务10开始执行,当前线程名为pool-1-thread-1
任务10执行完毕,当前线程名为pool-1-thread-1
package com.executor;import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**** 功能描述: ScheduledThreadPool是一个可以执行定时任务的线程池,可以实现延迟执行和周期执行。** @param: * @return: * @auther: csh* @date: 2023/3/6 11:13 下午*/
public class ScheduledThreadPoolStudy {public static void main(String[] args) {// 创建一个可以执行定时任务的线程池ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);// 提交10个定时任务,每个任务延迟1秒后执行,每个任务执行周期为2秒for (int i = 1; i <= 10; i++) {scheduledExecutorService.scheduleAtFixedRate(new Task(i), 1, 2, TimeUnit.SECONDS);}// 关闭线程池// scheduledExecutorService.shutdown();}static class Task implements Runnable {private int taskId;public Task(int taskId) {this.taskId = taskId;}@Overridepublic void run() {System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());try {// 模拟任务执行的耗时Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());}}
}

结果 可以看到 实现了周期性执行

任务4开始执行,当前线程名为pool-1-thread-2
任务10执行完毕,当前线程名为pool-1-thread-3
任务5开始执行,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-4
任务7开始执行,当前线程名为pool-1-thread-4
任务3执行完毕,当前线程名为pool-1-thread-5
任务8开始执行,当前线程名为pool-1-thread-5
任务4执行完毕,当前线程名为pool-1-thread-2
任务9开始执行,当前线程名为pool-1-thread-2
任务5执行完毕,当前线程名为pool-1-thread-3
任务10开始执行,当前线程名为pool-1-thread-3
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务7执行完毕,当前线程名为pool-1-thread-4
任务2开始执行,当前线程名为pool-1-thread-4
任务8执行完毕,当前线程名为pool-1-thread-5
任务3开始执行,当前线程名为pool-1-thread-5
任务9执行完毕,当前线程名为pool-1-thread-2
任务4开始执行,当前线程名为pool-1-thread-2
任务10执行完毕,当前线程名为pool-1-thread-3
任务5开始执行,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-4
任务7开始执行,当前线程名为pool-1-thread-4
任务3执行完毕,当前线程名为pool-1-thread-5
任务8开始执行,当前线程名为pool-1-thread-5
任务4执行完毕,当前线程名为pool-1-thread-2
任务9开始执行,当前线程名为pool-1-thread-2
任务5执行完毕,当前线程名为pool-1-thread-3
任务10开始执行,当前线程名为pool-1-thread-3
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务8执行完毕,当前线程名为pool-1-thread-5
任务2开始执行,当前线程名为pool-1-thread-5
任务7执行完毕,当前线程名为pool-1-thread-4
任务3开始执行,当前线程名为pool-1-thread-4
任务9执行完毕,当前线程名为pool-1-thread-2
任务10执行完毕,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-2
任务5开始执行,当前线程名为pool-1-thread-3
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-5
任务7开始执行,当前线程名为pool-1-thread-5
任务3执行完毕,当前线程名为pool-1-thread-4
任务8开始执行,当前线程名为pool-1-thread-4
任务4执行完毕,当前线程名为pool-1-thread-2
任务5执行完毕,当前线程名为pool-1-thread-3
任务9开始执行,当前线程名为pool-1-thread-3
任务10开始执行,当前线程名为pool-1-thread-2
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务8执行完毕,当前线程名为pool-1-thread-4
任务2开始执行,当前线程名为pool-1-thread-4
任务7执行完毕,当前线程名为pool-1-thread-5
任务3开始执行,当前线程名为pool-1-thread-5
任务9执行完毕,当前线程名为pool-1-thread-3
任务10执行完毕,当前线程名为pool-1-thread-2
任务4开始执行,当前线程名为pool-1-thread-3
任务5开始执行,当前线程名为pool-1-thread-2
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务3执行完毕,当前线程名为pool-1-thread-5
任务7开始执行,当前线程名为pool-1-thread-5
任务2执行完毕,当前线程名为pool-1-thread-4
任务8开始执行,当前线程名为pool-1-thread-4
任务4执行完毕,当前线程名为pool-1-thread-3
任务5执行完毕,当前线程名为pool-1-thread-2
任务9开始执行,当前线程名为pool-1-thread-3
任务10开始执行,当前线程名为pool-1-thread-2
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务7执行完毕,当前线程名为pool-1-thread-5
任务2开始执行,当前线程名为pool-1-thread-5
任务8执行完毕,当前线程名为pool-1-thread-4
任务3开始执行,当前线程名为pool-1-thread-4
任务9执行完毕,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-3
任务10执行完毕,当前线程名为pool-1-thread-2
任务5开始执行,当前线程名为pool-1-thread-2
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务2执行完毕,当前线程名为pool-1-thread-5
任务7开始执行,当前线程名为pool-1-thread-5
任务3执行完毕,当前线程名为pool-1-thread-4
任务8开始执行,当前线程名为pool-1-thread-4
任务4执行完毕,当前线程名为pool-1-thread-3
任务9开始执行,当前线程名为pool-1-thread-3
任务5执行完毕,当前线程名为pool-1-thread-2
任务10开始执行,当前线程名为pool-1-thread-2
任务6执行完毕,当前线程名为pool-1-thread-1
任务1开始执行,当前线程名为pool-1-thread-1
任务8执行完毕,当前线程名为pool-1-thread-4
任务7执行完毕,当前线程名为pool-1-thread-5
任务2开始执行,当前线程名为pool-1-thread-4
任务3开始执行,当前线程名为pool-1-thread-5
任务9执行完毕,当前线程名为pool-1-thread-3
任务4开始执行,当前线程名为pool-1-thread-3
任务10执行完毕,当前线程名为pool-1-thread-2
任务5开始执行,当前线程名为pool-1-thread-2
任务1执行完毕,当前线程名为pool-1-thread-1
任务6开始执行,当前线程名为pool-1-thread-1
任务3执行完毕,当前线程名为pool-1-thread-5
任务2执行完毕,当前线程名为pool-1-thread-4
任务7开始执行,当前线程名为pool-1-thread-5
任务8开始执行,当前线程名为pool-1-thread-4
任务4执行完毕,当前线程名为pool-1-thread-3
任务9开始执行,当前线程名为pool-1-thread-3
任务5执行完毕,当前线程名为pool-1-thread-2
任务10开始执行,当前线程名为pool-1-thread-2
package com.executor;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**** 功能描述: WorkStealingPool是一个基于工作窃取算法的线程池,用于提高多核CPU的利用率。** @param:* @return: * @auther: csh* @date: 2023/3/6 11:18 下午*/
public class WorkStealingPoolStudy {public static void main(String[] args) {// 获取当前系统的CPU核心数int processors = Runtime.getRuntime().availableProcessors();// 创建一个基于工作窃取算法的线程池ExecutorService executorService = Executors.newWorkStealingPool(processors);// 提交10个任务for (int i = 1; i <= 1000; i++) {executorService.execute(new Task(i));}// 等待所有任务执行完毕try {executorService.awaitTermination(1, TimeUnit.MINUTES);} catch (InterruptedException e) {e.printStackTrace();}// 关闭线程池executorService.shutdown();}static class Task implements Runnable {private int taskId;public Task(int taskId) {this.taskId = taskId;}@Overridepublic void run() {System.out.println("任务" + taskId + "开始执行,当前线程名为" + Thread.currentThread().getName());try {// 模拟任务执行的耗时Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("任务" + taskId + "执行完毕,当前线程名为" + Thread.currentThread().getName());}}
}

结果

任务8开始执行,当前线程名为ForkJoinPool-1-worker-0
任务4开始执行,当前线程名为ForkJoinPool-1-worker-4
任务5开始执行,当前线程名为ForkJoinPool-1-worker-5
任务2开始执行,当前线程名为ForkJoinPool-1-worker-2
任务3开始执行,当前线程名为ForkJoinPool-1-worker-3
任务6开始执行,当前线程名为ForkJoinPool-1-worker-6
任务1开始执行,当前线程名为ForkJoinPool-1-worker-1
任务7开始执行,当前线程名为ForkJoinPool-1-worker-7
任务8执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务1执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务2执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务5执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务12开始执行,当前线程名为ForkJoinPool-1-worker-5
任务4执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务13开始执行,当前线程名为ForkJoinPool-1-worker-4
任务7执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务14开始执行,当前线程名为ForkJoinPool-1-worker-7
任务11开始执行,当前线程名为ForkJoinPool-1-worker-2
任务3执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务6执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务9开始执行,当前线程名为ForkJoinPool-1-worker-0
任务10开始执行,当前线程名为ForkJoinPool-1-worker-1
任务16开始执行,当前线程名为ForkJoinPool-1-worker-6
任务15开始执行,当前线程名为ForkJoinPool-1-worker-3
任务12执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务10执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务18开始执行,当前线程名为ForkJoinPool-1-worker-1
任务15执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务19开始执行,当前线程名为ForkJoinPool-1-worker-3
任务13执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务20开始执行,当前线程名为ForkJoinPool-1-worker-4
任务9执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务21开始执行,当前线程名为ForkJoinPool-1-worker-0
任务11执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务22开始执行,当前线程名为ForkJoinPool-1-worker-2
任务14执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务23开始执行,当前线程名为ForkJoinPool-1-worker-7
任务16执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务24开始执行,当前线程名为ForkJoinPool-1-worker-6
任务17开始执行,当前线程名为ForkJoinPool-1-worker-5
任务19执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务23执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务24执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务25开始执行,当前线程名为ForkJoinPool-1-worker-3
任务26开始执行,当前线程名为ForkJoinPool-1-worker-7
任务17执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务20执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务27开始执行,当前线程名为ForkJoinPool-1-worker-6
任务22执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务29开始执行,当前线程名为ForkJoinPool-1-worker-4
任务30开始执行,当前线程名为ForkJoinPool-1-worker-2
任务28开始执行,当前线程名为ForkJoinPool-1-worker-5
任务18执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务21执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务31开始执行,当前线程名为ForkJoinPool-1-worker-1
任务32开始执行,当前线程名为ForkJoinPool-1-worker-0
任务26执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务29执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务30执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务33开始执行,当前线程名为ForkJoinPool-1-worker-7
任务31执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务27执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务25执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务28执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务38开始执行,当前线程名为ForkJoinPool-1-worker-3
任务37开始执行,当前线程名为ForkJoinPool-1-worker-6
任务36开始执行,当前线程名为ForkJoinPool-1-worker-1
任务35开始执行,当前线程名为ForkJoinPool-1-worker-4
任务34开始执行,当前线程名为ForkJoinPool-1-worker-2
任务39开始执行,当前线程名为ForkJoinPool-1-worker-5
任务32执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务40开始执行,当前线程名为ForkJoinPool-1-worker-0
任务34执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务41开始执行,当前线程名为ForkJoinPool-1-worker-2
任务39执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务42开始执行,当前线程名为ForkJoinPool-1-worker-5
任务35执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务43开始执行,当前线程名为ForkJoinPool-1-worker-4
任务36执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务44开始执行,当前线程名为ForkJoinPool-1-worker-1
任务33执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务38执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务45开始执行,当前线程名为ForkJoinPool-1-worker-3
任务46开始执行,当前线程名为ForkJoinPool-1-worker-7
任务37执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务47开始执行,当前线程名为ForkJoinPool-1-worker-6
任务40执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务48开始执行,当前线程名为ForkJoinPool-1-worker-0
任务44执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务49开始执行,当前线程名为ForkJoinPool-1-worker-1
任务42执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务43执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务45执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务41执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务52开始执行,当前线程名为ForkJoinPool-1-worker-3
任务51开始执行,当前线程名为ForkJoinPool-1-worker-4
任务50开始执行,当前线程名为ForkJoinPool-1-worker-5
任务53开始执行,当前线程名为ForkJoinPool-1-worker-2
任务47执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务54开始执行,当前线程名为ForkJoinPool-1-worker-6
任务46执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务48执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务55开始执行,当前线程名为ForkJoinPool-1-worker-7
任务56开始执行,当前线程名为ForkJoinPool-1-worker-0
任务49执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务57开始执行,当前线程名为ForkJoinPool-1-worker-1
任务51执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务58开始执行,当前线程名为ForkJoinPool-1-worker-4
任务52执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务59开始执行,当前线程名为ForkJoinPool-1-worker-3
任务53执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务60开始执行,当前线程名为ForkJoinPool-1-worker-2
任务56执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务54执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务61开始执行,当前线程名为ForkJoinPool-1-worker-0
任务55执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务63开始执行,当前线程名为ForkJoinPool-1-worker-7
任务50执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务64开始执行,当前线程名为ForkJoinPool-1-worker-5
任务62开始执行,当前线程名为ForkJoinPool-1-worker-6
任务57执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务62执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务64执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务60执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务63执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务59执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务61执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务67开始执行,当前线程名为ForkJoinPool-1-worker-2
任务58执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务68开始执行,当前线程名为ForkJoinPool-1-worker-6
任务71开始执行,当前线程名为ForkJoinPool-1-worker-0
任务72开始执行,当前线程名为ForkJoinPool-1-worker-4
任务69开始执行,当前线程名为ForkJoinPool-1-worker-7
任务70开始执行,当前线程名为ForkJoinPool-1-worker-3
任务66开始执行,当前线程名为ForkJoinPool-1-worker-5
任务65开始执行,当前线程名为ForkJoinPool-1-worker-1
任务67执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务66执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务65执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务70执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务72执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务68执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务71执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务69执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务79开始执行,当前线程名为ForkJoinPool-1-worker-0
任务78开始执行,当前线程名为ForkJoinPool-1-worker-6
任务77开始执行,当前线程名为ForkJoinPool-1-worker-4
任务76开始执行,当前线程名为ForkJoinPool-1-worker-3
任务75开始执行,当前线程名为ForkJoinPool-1-worker-1
任务74开始执行,当前线程名为ForkJoinPool-1-worker-5
任务73开始执行,当前线程名为ForkJoinPool-1-worker-2
任务80开始执行,当前线程名为ForkJoinPool-1-worker-7
任务75执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务79执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务73执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务76执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务84开始执行,当前线程名为ForkJoinPool-1-worker-3
任务78执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务82开始执行,当前线程名为ForkJoinPool-1-worker-0
任务81开始执行,当前线程名为ForkJoinPool-1-worker-1
任务85开始执行,当前线程名为ForkJoinPool-1-worker-6
任务83开始执行,当前线程名为ForkJoinPool-1-worker-2
任务80执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务86开始执行,当前线程名为ForkJoinPool-1-worker-7
任务74执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务77执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务87开始执行,当前线程名为ForkJoinPool-1-worker-5
任务88开始执行,当前线程名为ForkJoinPool-1-worker-4
任务82执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务84执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务89开始执行,当前线程名为ForkJoinPool-1-worker-3
任务81执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务85执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务86执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务90开始执行,当前线程名为ForkJoinPool-1-worker-1
任务83执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务92开始执行,当前线程名为ForkJoinPool-1-worker-2
任务91开始执行,当前线程名为ForkJoinPool-1-worker-0
任务93开始执行,当前线程名为ForkJoinPool-1-worker-6
任务94开始执行,当前线程名为ForkJoinPool-1-worker-7
任务88执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务95开始执行,当前线程名为ForkJoinPool-1-worker-4
任务87执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务96开始执行,当前线程名为ForkJoinPool-1-worker-5
任务92执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务94执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务98开始执行,当前线程名为ForkJoinPool-1-worker-7
任务95执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务99开始执行,当前线程名为ForkJoinPool-1-worker-4
任务97开始执行,当前线程名为ForkJoinPool-1-worker-2
任务89执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务100开始执行,当前线程名为ForkJoinPool-1-worker-3
任务91执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务101开始执行,当前线程名为ForkJoinPool-1-worker-0
任务93执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务102开始执行,当前线程名为ForkJoinPool-1-worker-6
任务90执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务103开始执行,当前线程名为ForkJoinPool-1-worker-1
任务96执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务104开始执行,当前线程名为ForkJoinPool-1-worker-5
任务97执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务104执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务101执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务100执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务105开始执行,当前线程名为ForkJoinPool-1-worker-2
任务99执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务107开始执行,当前线程名为ForkJoinPool-1-worker-4
任务108开始执行,当前线程名为ForkJoinPool-1-worker-5
任务98执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务109开始执行,当前线程名为ForkJoinPool-1-worker-7
任务102执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务111开始执行,当前线程名为ForkJoinPool-1-worker-6
任务103执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务110开始执行,当前线程名为ForkJoinPool-1-worker-0
任务106开始执行,当前线程名为ForkJoinPool-1-worker-3
任务112开始执行,当前线程名为ForkJoinPool-1-worker-1
任务110执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务112执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务113开始执行,当前线程名为ForkJoinPool-1-worker-0
任务107执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务114开始执行,当前线程名为ForkJoinPool-1-worker-1
任务115开始执行,当前线程名为ForkJoinPool-1-worker-4
任务105执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务111执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务109执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务108执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务106执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务119开始执行,当前线程名为ForkJoinPool-1-worker-5
任务118开始执行,当前线程名为ForkJoinPool-1-worker-7
任务117开始执行,当前线程名为ForkJoinPool-1-worker-6
任务116开始执行,当前线程名为ForkJoinPool-1-worker-2
任务120开始执行,当前线程名为ForkJoinPool-1-worker-3
任务114执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务121开始执行,当前线程名为ForkJoinPool-1-worker-1
任务113执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务115执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务122开始执行,当前线程名为ForkJoinPool-1-worker-4
任务123开始执行,当前线程名为ForkJoinPool-1-worker-0
任务116执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务118执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务124开始执行,当前线程名为ForkJoinPool-1-worker-2
任务125开始执行,当前线程名为ForkJoinPool-1-worker-7
任务119执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务120执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务117执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务126开始执行,当前线程名为ForkJoinPool-1-worker-5
任务128开始执行,当前线程名为ForkJoinPool-1-worker-6
任务127开始执行,当前线程名为ForkJoinPool-1-worker-3
任务125执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务129开始执行,当前线程名为ForkJoinPool-1-worker-7
任务123执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务130开始执行,当前线程名为ForkJoinPool-1-worker-0
任务121执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务124执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务122执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务133开始执行,当前线程名为ForkJoinPool-1-worker-4
任务132开始执行,当前线程名为ForkJoinPool-1-worker-2
任务131开始执行,当前线程名为ForkJoinPool-1-worker-1
任务128执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务127执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务126执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务135开始执行,当前线程名为ForkJoinPool-1-worker-3
任务134开始执行,当前线程名为ForkJoinPool-1-worker-6
任务136开始执行,当前线程名为ForkJoinPool-1-worker-5
任务129执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务132执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务130执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务131执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务133执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务137开始执行,当前线程名为ForkJoinPool-1-worker-7
任务138开始执行,当前线程名为ForkJoinPool-1-worker-2
任务141开始执行,当前线程名为ForkJoinPool-1-worker-4
任务139开始执行,当前线程名为ForkJoinPool-1-worker-0
任务140开始执行,当前线程名为ForkJoinPool-1-worker-1
任务134执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务135执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务136执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务143开始执行,当前线程名为ForkJoinPool-1-worker-3
任务144开始执行,当前线程名为ForkJoinPool-1-worker-5
任务142开始执行,当前线程名为ForkJoinPool-1-worker-6
任务137执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务141执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务145开始执行,当前线程名为ForkJoinPool-1-worker-7
任务138执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务146开始执行,当前线程名为ForkJoinPool-1-worker-4
任务139执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务147开始执行,当前线程名为ForkJoinPool-1-worker-2
任务148开始执行,当前线程名为ForkJoinPool-1-worker-0
任务140执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务149开始执行,当前线程名为ForkJoinPool-1-worker-1
任务143执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务142执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务150开始执行,当前线程名为ForkJoinPool-1-worker-3
任务151开始执行,当前线程名为ForkJoinPool-1-worker-6
任务144执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务152开始执行,当前线程名为ForkJoinPool-1-worker-5
任务145执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务153开始执行,当前线程名为ForkJoinPool-1-worker-7
任务148执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务149执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务154开始执行,当前线程名为ForkJoinPool-1-worker-0
任务155开始执行,当前线程名为ForkJoinPool-1-worker-1
任务146执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务147执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务157开始执行,当前线程名为ForkJoinPool-1-worker-2
任务156开始执行,当前线程名为ForkJoinPool-1-worker-4
任务151执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务158开始执行,当前线程名为ForkJoinPool-1-worker-6
任务152执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务159开始执行,当前线程名为ForkJoinPool-1-worker-5
任务150执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务160开始执行,当前线程名为ForkJoinPool-1-worker-3
任务157执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务161开始执行,当前线程名为ForkJoinPool-1-worker-2
任务158执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务162开始执行,当前线程名为ForkJoinPool-1-worker-6
任务155执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务153执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务163开始执行,当前线程名为ForkJoinPool-1-worker-1
任务164开始执行,当前线程名为ForkJoinPool-1-worker-7
任务156执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务165开始执行,当前线程名为ForkJoinPool-1-worker-4
任务154执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务166开始执行,当前线程名为ForkJoinPool-1-worker-0
任务159执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务167开始执行,当前线程名为ForkJoinPool-1-worker-5
任务160执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务168开始执行,当前线程名为ForkJoinPool-1-worker-3
任务161执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务169开始执行,当前线程名为ForkJoinPool-1-worker-2
任务164执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务163执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务170开始执行,当前线程名为ForkJoinPool-1-worker-7
任务171开始执行,当前线程名为ForkJoinPool-1-worker-1
任务165执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务166执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务162执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务173开始执行,当前线程名为ForkJoinPool-1-worker-0
任务172开始执行,当前线程名为ForkJoinPool-1-worker-4
任务174开始执行,当前线程名为ForkJoinPool-1-worker-6
任务167执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务175开始执行,当前线程名为ForkJoinPool-1-worker-5
任务168执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务176开始执行,当前线程名为ForkJoinPool-1-worker-3
任务171执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务174执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务177开始执行,当前线程名为ForkJoinPool-1-worker-1
任务178开始执行,当前线程名为ForkJoinPool-1-worker-6
任务169执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务173执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务179开始执行,当前线程名为ForkJoinPool-1-worker-2
任务180开始执行,当前线程名为ForkJoinPool-1-worker-0
任务170执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务181开始执行,当前线程名为ForkJoinPool-1-worker-7
任务172执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务182开始执行,当前线程名为ForkJoinPool-1-worker-4
任务175执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务183开始执行,当前线程名为ForkJoinPool-1-worker-5
任务176执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务184开始执行,当前线程名为ForkJoinPool-1-worker-3
任务181执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务185开始执行,当前线程名为ForkJoinPool-1-worker-7
任务177执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务180执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务186开始执行,当前线程名为ForkJoinPool-1-worker-1
任务187开始执行,当前线程名为ForkJoinPool-1-worker-0
任务178执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务179执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务189开始执行,当前线程名为ForkJoinPool-1-worker-2
任务188开始执行,当前线程名为ForkJoinPool-1-worker-6
任务182执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务190开始执行,当前线程名为ForkJoinPool-1-worker-4
任务183执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务184执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务191开始执行,当前线程名为ForkJoinPool-1-worker-5
任务192开始执行,当前线程名为ForkJoinPool-1-worker-3
任务185执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务193开始执行,当前线程名为ForkJoinPool-1-worker-7
任务186执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务187执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务188执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务194开始执行,当前线程名为ForkJoinPool-1-worker-1
任务189执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务197开始执行,当前线程名为ForkJoinPool-1-worker-2
任务195开始执行,当前线程名为ForkJoinPool-1-worker-0
任务190执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务198开始执行,当前线程名为ForkJoinPool-1-worker-4
任务196开始执行,当前线程名为ForkJoinPool-1-worker-6
任务192执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务199开始执行,当前线程名为ForkJoinPool-1-worker-3
任务191执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务200开始执行,当前线程名为ForkJoinPool-1-worker-5
任务194执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务197执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务202开始执行,当前线程名为ForkJoinPool-1-worker-2
任务201开始执行,当前线程名为ForkJoinPool-1-worker-1
任务193执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务203开始执行,当前线程名为ForkJoinPool-1-worker-7
任务198执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务195执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务205开始执行,当前线程名为ForkJoinPool-1-worker-0
任务204开始执行,当前线程名为ForkJoinPool-1-worker-4
任务196执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务206开始执行,当前线程名为ForkJoinPool-1-worker-6
任务199执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务207开始执行,当前线程名为ForkJoinPool-1-worker-3
任务200执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务208开始执行,当前线程名为ForkJoinPool-1-worker-5
任务203执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务209开始执行,当前线程名为ForkJoinPool-1-worker-7
任务202执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务210开始执行,当前线程名为ForkJoinPool-1-worker-2
任务201执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务211开始执行,当前线程名为ForkJoinPool-1-worker-1
任务205执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务212开始执行,当前线程名为ForkJoinPool-1-worker-0
任务206执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务213开始执行,当前线程名为ForkJoinPool-1-worker-6
任务204执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务214开始执行,当前线程名为ForkJoinPool-1-worker-4
任务207执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务215开始执行,当前线程名为ForkJoinPool-1-worker-3
任务208执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务216开始执行,当前线程名为ForkJoinPool-1-worker-5
任务209执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务217开始执行,当前线程名为ForkJoinPool-1-worker-7
任务213执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务212执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务219开始执行,当前线程名为ForkJoinPool-1-worker-0
任务211执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务210执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务221开始执行,当前线程名为ForkJoinPool-1-worker-2
任务220开始执行,当前线程名为ForkJoinPool-1-worker-1
任务218开始执行,当前线程名为ForkJoinPool-1-worker-6
任务214执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务222开始执行,当前线程名为ForkJoinPool-1-worker-4
任务215执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务223开始执行,当前线程名为ForkJoinPool-1-worker-3
任务216执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务224开始执行,当前线程名为ForkJoinPool-1-worker-5
任务217执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务225开始执行,当前线程名为ForkJoinPool-1-worker-7
任务221执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务218执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务226开始执行,当前线程名为ForkJoinPool-1-worker-2
任务219执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务227开始执行,当前线程名为ForkJoinPool-1-worker-6
任务228开始执行,当前线程名为ForkJoinPool-1-worker-0
任务220执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务229开始执行,当前线程名为ForkJoinPool-1-worker-1
任务222执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务224执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务230开始执行,当前线程名为ForkJoinPool-1-worker-4
任务231开始执行,当前线程名为ForkJoinPool-1-worker-5
任务223执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务232开始执行,当前线程名为ForkJoinPool-1-worker-3
任务225执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务233开始执行,当前线程名为ForkJoinPool-1-worker-7
任务226执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务227执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务234开始执行,当前线程名为ForkJoinPool-1-worker-2
任务228执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务236开始执行,当前线程名为ForkJoinPool-1-worker-0
任务235开始执行,当前线程名为ForkJoinPool-1-worker-6
任务229执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务237开始执行,当前线程名为ForkJoinPool-1-worker-1
任务230执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务238开始执行,当前线程名为ForkJoinPool-1-worker-4
任务231执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务239开始执行,当前线程名为ForkJoinPool-1-worker-5
任务232执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务240开始执行,当前线程名为ForkJoinPool-1-worker-3
任务236执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务237执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务233执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务242开始执行,当前线程名为ForkJoinPool-1-worker-1
任务243开始执行,当前线程名为ForkJoinPool-1-worker-7
任务241开始执行,当前线程名为ForkJoinPool-1-worker-0
任务234执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务235执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务244开始执行,当前线程名为ForkJoinPool-1-worker-2
任务245开始执行,当前线程名为ForkJoinPool-1-worker-6
任务240执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务238执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务246开始执行,当前线程名为ForkJoinPool-1-worker-4
任务239执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务247开始执行,当前线程名为ForkJoinPool-1-worker-3
任务248开始执行,当前线程名为ForkJoinPool-1-worker-5
任务243执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务249开始执行,当前线程名为ForkJoinPool-1-worker-7
任务244执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务242执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务250开始执行,当前线程名为ForkJoinPool-1-worker-2
任务251开始执行,当前线程名为ForkJoinPool-1-worker-1
任务245执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务241执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务252开始执行,当前线程名为ForkJoinPool-1-worker-6
任务253开始执行,当前线程名为ForkJoinPool-1-worker-0
任务246执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务248执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务254开始执行,当前线程名为ForkJoinPool-1-worker-4
任务255开始执行,当前线程名为ForkJoinPool-1-worker-5
任务247执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务256开始执行,当前线程名为ForkJoinPool-1-worker-3
任务249执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务250执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务252执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务254执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务251执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务253执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务261开始执行,当前线程名为ForkJoinPool-1-worker-6
任务262开始执行,当前线程名为ForkJoinPool-1-worker-1
任务257开始执行,当前线程名为ForkJoinPool-1-worker-7
任务259开始执行,当前线程名为ForkJoinPool-1-worker-0
任务260开始执行,当前线程名为ForkJoinPool-1-worker-4
任务258开始执行,当前线程名为ForkJoinPool-1-worker-2
任务255执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务263开始执行,当前线程名为ForkJoinPool-1-worker-5
任务256执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务264开始执行,当前线程名为ForkJoinPool-1-worker-3
任务262执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务260执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务261执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务258执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务257执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务259执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务263执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务264执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务265开始执行,当前线程名为ForkJoinPool-1-worker-3
任务266开始执行,当前线程名为ForkJoinPool-1-worker-6
任务267开始执行,当前线程名为ForkJoinPool-1-worker-5
任务268开始执行,当前线程名为ForkJoinPool-1-worker-1
任务269开始执行,当前线程名为ForkJoinPool-1-worker-4
任务270开始执行,当前线程名为ForkJoinPool-1-worker-2
任务271开始执行,当前线程名为ForkJoinPool-1-worker-0
任务272开始执行,当前线程名为ForkJoinPool-1-worker-7
任务267执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务270执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务272执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务271执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务266执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务269执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务265执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务273开始执行,当前线程名为ForkJoinPool-1-worker-5
任务268执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务274开始执行,当前线程名为ForkJoinPool-1-worker-1
任务275开始执行,当前线程名为ForkJoinPool-1-worker-2
任务276开始执行,当前线程名为ForkJoinPool-1-worker-7
任务277开始执行,当前线程名为ForkJoinPool-1-worker-3
任务278开始执行,当前线程名为ForkJoinPool-1-worker-6
任务279开始执行,当前线程名为ForkJoinPool-1-worker-4
任务280开始执行,当前线程名为ForkJoinPool-1-worker-0
任务273执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务279执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务282开始执行,当前线程名为ForkJoinPool-1-worker-4
任务278执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务283开始执行,当前线程名为ForkJoinPool-1-worker-6
任务277执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务284开始执行,当前线程名为ForkJoinPool-1-worker-3
任务276执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务285开始执行,当前线程名为ForkJoinPool-1-worker-7
任务275执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务286开始执行,当前线程名为ForkJoinPool-1-worker-2
任务281开始执行,当前线程名为ForkJoinPool-1-worker-5
任务274执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务287开始执行,当前线程名为ForkJoinPool-1-worker-1
任务280执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务288开始执行,当前线程名为ForkJoinPool-1-worker-0
任务283执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务285执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务289开始执行,当前线程名为ForkJoinPool-1-worker-6
任务281执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务291开始执行,当前线程名为ForkJoinPool-1-worker-5
任务290开始执行,当前线程名为ForkJoinPool-1-worker-7
任务284执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务286执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务293开始执行,当前线程名为ForkJoinPool-1-worker-2
任务282执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务294开始执行,当前线程名为ForkJoinPool-1-worker-4
任务288执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务295开始执行,当前线程名为ForkJoinPool-1-worker-0
任务287执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务296开始执行,当前线程名为ForkJoinPool-1-worker-1
任务292开始执行,当前线程名为ForkJoinPool-1-worker-3
任务291执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务290执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务289执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务298开始执行,当前线程名为ForkJoinPool-1-worker-7
任务297开始执行,当前线程名为ForkJoinPool-1-worker-5
任务299开始执行,当前线程名为ForkJoinPool-1-worker-6
任务294执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务296执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务301开始执行,当前线程名为ForkJoinPool-1-worker-1
任务295执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务300开始执行,当前线程名为ForkJoinPool-1-worker-4
任务302开始执行,当前线程名为ForkJoinPool-1-worker-0
任务292执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务293执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务304开始执行,当前线程名为ForkJoinPool-1-worker-2
任务303开始执行,当前线程名为ForkJoinPool-1-worker-3
任务297执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务305开始执行,当前线程名为ForkJoinPool-1-worker-5
任务298执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务306开始执行,当前线程名为ForkJoinPool-1-worker-7
任务300执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务307开始执行,当前线程名为ForkJoinPool-1-worker-4
任务299执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务308开始执行,当前线程名为ForkJoinPool-1-worker-6
任务303执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务309开始执行,当前线程名为ForkJoinPool-1-worker-3
任务301执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务310开始执行,当前线程名为ForkJoinPool-1-worker-1
任务302执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务304执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务312开始执行,当前线程名为ForkJoinPool-1-worker-2
任务311开始执行,当前线程名为ForkJoinPool-1-worker-0
任务305执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务313开始执行,当前线程名为ForkJoinPool-1-worker-5
任务308执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务309执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务315开始执行,当前线程名为ForkJoinPool-1-worker-3
任务307执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务316开始执行,当前线程名为ForkJoinPool-1-worker-4
任务310执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务312执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务318开始执行,当前线程名为ForkJoinPool-1-worker-2
任务314开始执行,当前线程名为ForkJoinPool-1-worker-6
任务317开始执行,当前线程名为ForkJoinPool-1-worker-1
任务311执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务319开始执行,当前线程名为ForkJoinPool-1-worker-0
任务306执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务320开始执行,当前线程名为ForkJoinPool-1-worker-7
任务313执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务321开始执行,当前线程名为ForkJoinPool-1-worker-5
任务319执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务317执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务322开始执行,当前线程名为ForkJoinPool-1-worker-1
任务323开始执行,当前线程名为ForkJoinPool-1-worker-0
任务314执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务324开始执行,当前线程名为ForkJoinPool-1-worker-6
任务318执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务325开始执行,当前线程名为ForkJoinPool-1-worker-2
任务320执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务326开始执行,当前线程名为ForkJoinPool-1-worker-7
任务315执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务316执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务327开始执行,当前线程名为ForkJoinPool-1-worker-3
任务328开始执行,当前线程名为ForkJoinPool-1-worker-4
任务321执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务329开始执行,当前线程名为ForkJoinPool-1-worker-5
任务324执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务323执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务328执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务327执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务332开始执行,当前线程名为ForkJoinPool-1-worker-3
任务333开始执行,当前线程名为ForkJoinPool-1-worker-4
任务322执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务334开始执行,当前线程名为ForkJoinPool-1-worker-1
任务330开始执行,当前线程名为ForkJoinPool-1-worker-6
任务331开始执行,当前线程名为ForkJoinPool-1-worker-0
任务325执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务335开始执行,当前线程名为ForkJoinPool-1-worker-2
任务326执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务336开始执行,当前线程名为ForkJoinPool-1-worker-7
任务329执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务337开始执行,当前线程名为ForkJoinPool-1-worker-5
任务332执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务338开始执行,当前线程名为ForkJoinPool-1-worker-3
任务335执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务339开始执行,当前线程名为ForkJoinPool-1-worker-2
任务333执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务340开始执行,当前线程名为ForkJoinPool-1-worker-4
任务334执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务341开始执行,当前线程名为ForkJoinPool-1-worker-1
任务330执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务342开始执行,当前线程名为ForkJoinPool-1-worker-6
任务331执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务343开始执行,当前线程名为ForkJoinPool-1-worker-0
任务336执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务344开始执行,当前线程名为ForkJoinPool-1-worker-7
任务337执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务345开始执行,当前线程名为ForkJoinPool-1-worker-5
任务339执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务346开始执行,当前线程名为ForkJoinPool-1-worker-2
任务338执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务347开始执行,当前线程名为ForkJoinPool-1-worker-3
任务340执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务348开始执行,当前线程名为ForkJoinPool-1-worker-4
任务341执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务342执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务349开始执行,当前线程名为ForkJoinPool-1-worker-1
任务350开始执行,当前线程名为ForkJoinPool-1-worker-6
任务343执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务351开始执行,当前线程名为ForkJoinPool-1-worker-0
任务344执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务352开始执行,当前线程名为ForkJoinPool-1-worker-7
任务345执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务353开始执行,当前线程名为ForkJoinPool-1-worker-5
任务349执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务354开始执行,当前线程名为ForkJoinPool-1-worker-1
任务346执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务355开始执行,当前线程名为ForkJoinPool-1-worker-2
任务347执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务356开始执行,当前线程名为ForkJoinPool-1-worker-3
任务351执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务357开始执行,当前线程名为ForkJoinPool-1-worker-0
任务348执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务358开始执行,当前线程名为ForkJoinPool-1-worker-4
任务350执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务359开始执行,当前线程名为ForkJoinPool-1-worker-6
任务352执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务360开始执行,当前线程名为ForkJoinPool-1-worker-7
任务353执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务361开始执行,当前线程名为ForkJoinPool-1-worker-5
任务354执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务355执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务362开始执行,当前线程名为ForkJoinPool-1-worker-1
任务363开始执行,当前线程名为ForkJoinPool-1-worker-2
任务357执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务364开始执行,当前线程名为ForkJoinPool-1-worker-0
任务356执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务359执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务366开始执行,当前线程名为ForkJoinPool-1-worker-6
任务365开始执行,当前线程名为ForkJoinPool-1-worker-3
任务358执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务367开始执行,当前线程名为ForkJoinPool-1-worker-4
任务360执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务368开始执行,当前线程名为ForkJoinPool-1-worker-7
任务361执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务369开始执行,当前线程名为ForkJoinPool-1-worker-5
任务364执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务366执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务370开始执行,当前线程名为ForkJoinPool-1-worker-6
任务371开始执行,当前线程名为ForkJoinPool-1-worker-0
任务362执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务372开始执行,当前线程名为ForkJoinPool-1-worker-1
任务363执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务373开始执行,当前线程名为ForkJoinPool-1-worker-2
任务365执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务374开始执行,当前线程名为ForkJoinPool-1-worker-3
任务367执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务375开始执行,当前线程名为ForkJoinPool-1-worker-4
任务368执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务376开始执行,当前线程名为ForkJoinPool-1-worker-7
任务369执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务377开始执行,当前线程名为ForkJoinPool-1-worker-5
任务371执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务370执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务378开始执行,当前线程名为ForkJoinPool-1-worker-0
任务379开始执行,当前线程名为ForkJoinPool-1-worker-6
任务372执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务373执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务380开始执行,当前线程名为ForkJoinPool-1-worker-1
任务381开始执行,当前线程名为ForkJoinPool-1-worker-2
任务374执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务382开始执行,当前线程名为ForkJoinPool-1-worker-3
任务375执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务383开始执行,当前线程名为ForkJoinPool-1-worker-4
任务376执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务384开始执行,当前线程名为ForkJoinPool-1-worker-7
任务377执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务385开始执行,当前线程名为ForkJoinPool-1-worker-5
任务381执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务378执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务386开始执行,当前线程名为ForkJoinPool-1-worker-2
任务383执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务379执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务380执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务389开始执行,当前线程名为ForkJoinPool-1-worker-1
任务382执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务390开始执行,当前线程名为ForkJoinPool-1-worker-3
任务388开始执行,当前线程名为ForkJoinPool-1-worker-4
任务387开始执行,当前线程名为ForkJoinPool-1-worker-0
任务391开始执行,当前线程名为ForkJoinPool-1-worker-6
任务384执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务392开始执行,当前线程名为ForkJoinPool-1-worker-7
任务385执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务393开始执行,当前线程名为ForkJoinPool-1-worker-5
任务389执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务388执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务387执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务390执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务391执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务398开始执行,当前线程名为ForkJoinPool-1-worker-6
任务397开始执行,当前线程名为ForkJoinPool-1-worker-1
任务396开始执行,当前线程名为ForkJoinPool-1-worker-0
任务394开始执行,当前线程名为ForkJoinPool-1-worker-4
任务395开始执行,当前线程名为ForkJoinPool-1-worker-3
任务386执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务399开始执行,当前线程名为ForkJoinPool-1-worker-2
任务392执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务400开始执行,当前线程名为ForkJoinPool-1-worker-7
任务393执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务401开始执行,当前线程名为ForkJoinPool-1-worker-5
任务397执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务399执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务402开始执行,当前线程名为ForkJoinPool-1-worker-1
任务395执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务404开始执行,当前线程名为ForkJoinPool-1-worker-3
任务394执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务405开始执行,当前线程名为ForkJoinPool-1-worker-4
任务398执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务406开始执行,当前线程名为ForkJoinPool-1-worker-6
任务396执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务407开始执行,当前线程名为ForkJoinPool-1-worker-0
任务403开始执行,当前线程名为ForkJoinPool-1-worker-2
任务400执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务408开始执行,当前线程名为ForkJoinPool-1-worker-7
任务401执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务409开始执行,当前线程名为ForkJoinPool-1-worker-5
任务403执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务410开始执行,当前线程名为ForkJoinPool-1-worker-2
任务402执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务405执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务404执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务413开始执行,当前线程名为ForkJoinPool-1-worker-3
任务411开始执行,当前线程名为ForkJoinPool-1-worker-1
任务406执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务414开始执行,当前线程名为ForkJoinPool-1-worker-6
任务412开始执行,当前线程名为ForkJoinPool-1-worker-4
任务407执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务415开始执行,当前线程名为ForkJoinPool-1-worker-0
任务408执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务416开始执行,当前线程名为ForkJoinPool-1-worker-7
任务409执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务417开始执行,当前线程名为ForkJoinPool-1-worker-5
任务410执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务418开始执行,当前线程名为ForkJoinPool-1-worker-2
任务413执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务419开始执行,当前线程名为ForkJoinPool-1-worker-3
任务415执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务420开始执行,当前线程名为ForkJoinPool-1-worker-0
任务412执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务421开始执行,当前线程名为ForkJoinPool-1-worker-4
任务414执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务422开始执行,当前线程名为ForkJoinPool-1-worker-6
任务411执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务423开始执行,当前线程名为ForkJoinPool-1-worker-1
任务416执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务424开始执行,当前线程名为ForkJoinPool-1-worker-7
任务417执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务425开始执行,当前线程名为ForkJoinPool-1-worker-5
任务422执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务426开始执行,当前线程名为ForkJoinPool-1-worker-6
任务419执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务420执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务421执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务429开始执行,当前线程名为ForkJoinPool-1-worker-4
任务427开始执行,当前线程名为ForkJoinPool-1-worker-3
任务418执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务430开始执行,当前线程名为ForkJoinPool-1-worker-2
任务428开始执行,当前线程名为ForkJoinPool-1-worker-0
任务423执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务431开始执行,当前线程名为ForkJoinPool-1-worker-1
任务424执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务432开始执行,当前线程名为ForkJoinPool-1-worker-7
任务425执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务433开始执行,当前线程名为ForkJoinPool-1-worker-5
任务426执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务434开始执行,当前线程名为ForkJoinPool-1-worker-6
任务427执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务435开始执行,当前线程名为ForkJoinPool-1-worker-3
任务430执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务436开始执行,当前线程名为ForkJoinPool-1-worker-2
任务428执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务437开始执行,当前线程名为ForkJoinPool-1-worker-0
任务429执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务438开始执行,当前线程名为ForkJoinPool-1-worker-4
任务431执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务439开始执行,当前线程名为ForkJoinPool-1-worker-1
任务432执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务440开始执行,当前线程名为ForkJoinPool-1-worker-7
任务433执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务441开始执行,当前线程名为ForkJoinPool-1-worker-5
任务434执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务442开始执行,当前线程名为ForkJoinPool-1-worker-6
任务437执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务443开始执行,当前线程名为ForkJoinPool-1-worker-0
任务435执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务436执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务445开始执行,当前线程名为ForkJoinPool-1-worker-2
任务444开始执行,当前线程名为ForkJoinPool-1-worker-3
任务439执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务446开始执行,当前线程名为ForkJoinPool-1-worker-1
任务438执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务447开始执行,当前线程名为ForkJoinPool-1-worker-4
任务440执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务448开始执行,当前线程名为ForkJoinPool-1-worker-7
任务441执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务449开始执行,当前线程名为ForkJoinPool-1-worker-5
任务442执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务450开始执行,当前线程名为ForkJoinPool-1-worker-6
任务443执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务451开始执行,当前线程名为ForkJoinPool-1-worker-0
任务444执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务452开始执行,当前线程名为ForkJoinPool-1-worker-3
任务446执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务445执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务454开始执行,当前线程名为ForkJoinPool-1-worker-2
任务453开始执行,当前线程名为ForkJoinPool-1-worker-1
任务447执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务455开始执行,当前线程名为ForkJoinPool-1-worker-4
任务448执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务456开始执行,当前线程名为ForkJoinPool-1-worker-7
任务449执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务457开始执行,当前线程名为ForkJoinPool-1-worker-5
任务450执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务458开始执行,当前线程名为ForkJoinPool-1-worker-6
任务451执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务452执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务459开始执行,当前线程名为ForkJoinPool-1-worker-0
任务460开始执行,当前线程名为ForkJoinPool-1-worker-3
任务453执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务461开始执行,当前线程名为ForkJoinPool-1-worker-1
任务455执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务462开始执行,当前线程名为ForkJoinPool-1-worker-4
任务454执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务463开始执行,当前线程名为ForkJoinPool-1-worker-2
任务456执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务464开始执行,当前线程名为ForkJoinPool-1-worker-7
任务457执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务465开始执行,当前线程名为ForkJoinPool-1-worker-5
任务458执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务466开始执行,当前线程名为ForkJoinPool-1-worker-6
任务460执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务467开始执行,当前线程名为ForkJoinPool-1-worker-3
任务459执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务468开始执行,当前线程名为ForkJoinPool-1-worker-0
任务463执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务469开始执行,当前线程名为ForkJoinPool-1-worker-2
任务461执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务470开始执行,当前线程名为ForkJoinPool-1-worker-1
任务462执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务471开始执行,当前线程名为ForkJoinPool-1-worker-4
任务464执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务472开始执行,当前线程名为ForkJoinPool-1-worker-7
任务465执行完毕,当前线程名为ForkJoinPool-1-worker-5
任务473开始执行,当前线程名为ForkJoinPool-1-worker-5
任务466执行完毕,当前线程名为ForkJoinPool-1-worker-6
任务474开始执行,当前线程名为ForkJoinPool-1-worker-6
任务467执行完毕,当前线程名为ForkJoinPool-1-worker-3
任务475开始执行,当前线程名为ForkJoinPool-1-worker-3
任务468执行完毕,当前线程名为ForkJoinPool-1-worker-0
任务476开始执行,当前线程名为ForkJoinPool-1-worker-0
任务469执行完毕,当前线程名为ForkJoinPool-1-worker-2
任务471执行完毕,当前线程名为ForkJoinPool-1-worker-4
任务478开始执行,当前线程名为ForkJoinPool-1-worker-4
任务470执行完毕,当前线程名为ForkJoinPool-1-worker-1
任务479开始执行,当前线程名为ForkJoinPool-1-worker-1
任务477开始执行,当前线程名为ForkJoinPool-1-worker-2
任务472执行完毕,当前线程名为ForkJoinPool-1-worker-7
任务480开始执行,当前线程名为ForkJoinPool-1-worker-7Process finished with exit code 0

注意这里同等配置,在苹果M1没压力,在windows CPU 8核的CPU飙高100%~

为什么要用线程池而不用Thread?

这个问题对于老手来说是废话,对于新手来说就要注意了。首先我不否认说直接用Thread不好,一切还是要看你的场景,如果你的整个系统只有一或几处thread,并且执行都是很短时间及次数很少,当然我不否认这样也是没有问题,但是如果你有以下的情况就要注意了。

1.执行次数非常频繁;

2.执行的地点非常多;

3.执行的线程时间长度不可预知或很长;

那么可能出现如下的情况:

1.CPU或内存忽高忽地,大半夜默名奇妙有告警;

2.经常不知道为什么FullGc;

3.代码耦合不敢乱改;

4.出现很多不可控因素,比如内存一直被占着,线程数量太高,系统卡顿 当然还有很多~

...

所以说线程池  统一管控(分配、调优、监控)资源 一定程度保障系统的稳定性,几大点如下:

  1. 资源控制:线程池可以限制同时运行的线程数量,防止过度消耗系统资源和导致系统崩溃。

  2. 提高效率:线程池可以重复利用已创建的线程,避免了频繁创建和销毁线程的开销,提高了程序的执行效率。

  3. 提高响应速度:线程池可以预先创建并初始化一定数量的线程,当任务到来时,可以立即执行,提高了程序的响应速度。

  4. 简化编程:使用线程池可以让程序员专注于业务逻辑的实现,而不必关心线程的创建和管理,简化了编程过程。使用线程池可以更好地控制系统资源、提高程序的效率和响应速度,并且简化编程过程。因此,在多线程编程中,使用线程池是一种更加优秀的选择。

源码学习

Executor框架

Executor框架是Java中用于管理线程池的框架,它提供了一种将任务提交和执行分离的机制,使得线程的创建和销毁可以由框架自动管理,从而减少了线程创建和上下文切换的开销,提高了系统的性能。Executor框架主要包含以下三个核心组件:

  1. Executor 接口:该接口定义了一个execute方法,用于将任务提交给线程池执行。

  2. ExecutorService 接口:该接口继承了Executor接口,并增加了一些管理线程池的方法,例如submit方法、shutdown方法等。

  3. ThreadPoolExecutor 类:该类是线程池的实现类,它提供了丰富的参数配置,可以根据不同的需求创建不同的线程池。例如,可以设置核心线程数、最大线程数、队列容量、拒绝策略等参数。使用Executor框架可以方便地实现线程池的创建和管理,提高系统的性能和稳定性。同时,Executor框架还提供了一些方便的工具类,例如Executors类、ScheduledExecutorService接口等,可以实现定时任务、延时任务、周期性任务等功能,非常适合于多线程编程和并发处理。

92b951a87cf67f9313e87c9e5f7795b2.png

java.util.concurrent.Executor

//该接口定义了线程池的基本执行方法
public interface Executor {//在将来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由Executor实现自行决定。Params: command -可运行任务抛出:RejectedExecutionException -如果该任务不能被接受执行NullPointerException -如果命令为空void execute(Runnable command);
}

java.util.concurrent.ExecutorService

/*** @author: csh* @Date: 2023/3/7 23:08* @Description:*/
public interface ExecutorServiceStudy {/*** shutdown方法用于关闭线程池,不会立即停止所有任务的执行,而是等待所有任务执行完毕后再关闭。*/void shutdown();/*** shutdownNow方法用于关闭线程池,并尝试停止所有正在执行的任务。*/List shutdownNow();/*** isShutdown方法用于判断线程池是否已经关闭。*/boolean isShutdown();/*** isTerminated方法用于判断线程池是否已经关闭,并且所有任务都已经执行完毕。*/boolean isTerminated();/*** awaitTermination方法用于等待线程池关闭,并且所有任务都已经执行完毕。*/boolean awaitTermination(long timeout, TimeUnit unit)throws InterruptedException;/*** submit方法用于提交一个Callable或Runnable任务到线程池,并返回一个Future对象,可以通过Future对象获取任务的执行结果或取消任务的执行。*/ Future submit(Callable task);/*** Submits提交一个可运行任务以供执行,并返回表示该任务的Future。Future的get方法将在成功完成时返回给定的结果。*/ Future submit(Runnable task, T result);/*** 提交一个可运行任务以供执行,并返回表示该任务的Future。Future的get方法将在成功完成时返回null。*/Future submit(Runnable task);/*** 执行给定的任务,在所有任务完成时返回包含它们的状态和结果的Futures列表。的未来。对于返回列表的每个元素,isDone都是true。*/ List> invokeAll(Collection> tasks)throws InterruptedException;/*** 带超时时间 同上类似*/ List> invokeAll(Collection> tasks,long timeout, TimeUnit unit)throws InterruptedException;/*** 执行给定的任务,如果有成功完成的任务,则返回成功完成的任务的结果(即,没有抛出异常)。在正常或异常返回时,未完成的任务将被取消。如果在执行此操作时修改了给定的集合,则此方法的结果是未定义的。*/ T invokeAny(Collection> tasks)throws InterruptedException, ExecutionException;/*** 同上类似 带超时时间*/ T invokeAny(Collection> tasks,long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;
}

java.util.concurrent.AbstractExecutorService

package java.util.concurrent;
import java.util.*;
//提供ExecutorService执行方法的默认实现。该类是一个抽象类仅供继承
public abstract class AbstractExecutorService implements ExecutorService {//为给定的可运行对象和默认值返回一个RunnableFuture。protected  RunnableFuture newTaskFor(Runnable runnable, T value) {return new FutureTask(runnable, value);}//同上protected  RunnableFuture newTaskFor(Callable callable) {return new FutureTask(callable);}//任务提交public Future submit(Runnable task) {if (task == null) throw new NullPointerException();//创建RunnableFutureRunnableFuture ftask = newTaskFor(task, null);//执行execute(ftask);//返回return ftask;}//任务提交//task为任务//result 为自定义返回结果public  Future submit(Runnable task, T result) {if (task == null) throw new NullPointerException();RunnableFuture ftask = newTaskFor(task, result);execute(ftask);return ftask;}//任务提交的方法public  Future submit(Callable task) {if (task == null) throw new NullPointerException();RunnableFuture ftask = newTaskFor(task);execute(ftask);return ftask;}/*** 该方法是实现唤醒任意一个方法*/private  T doInvokeAny(Collection> tasks,boolean timed, long nanos)throws InterruptedException, ExecutionException, TimeoutException {if (tasks == null)throw new NullPointerException();//获取长度int ntasks = tasks.size();//为0抛出异常if (ntasks == 0)throw new IllegalArgumentException();//创建阶列ArrayList> futures = new ArrayList>(ntasks);//这里一个ExecutorCompletionService ecs =new ExecutorCompletionService(this);// For efficiency, especially in executors with limited// parallelism, check to see if previously submitted tasks are// done before submitting more of them. This interleaving// plus the exception mechanics account for messiness of main// loop.try {// Record exceptions so that if we fail to obtain any// result, we can throw the last exception we got.ExecutionException ee = null;final long deadline = timed ? System.nanoTime() + nanos : 0L;Iterator> it = tasks.iterator();// Start one task for sure; the rest incrementally//确定开始的任务futures.add(ecs.submit(it.next()));--ntasks;//递减int active = 1;//循环调用for (;;) {//获取队列的头,如果没有为null (阻塞队列)Future f = ecs.poll();//为空if (f == null) {//如果大于0if (ntasks > 0) {--ntasks;//指向下一个节点futures.add(ecs.submit(it.next()));++active;}//为0 最后一个了,跳出else if (active == 0)break;//其他逻辑 传进来timed 为true 进行超时时间判断和计算else if (timed) {f = ecs.poll(nanos, TimeUnit.NANOSECONDS);if (f == null)throw new TimeoutException();nanos = deadline - System.nanoTime();}//所有都没有 检索并删除表示下一个已完成任务的Future,如果没有则等待。elsef = ecs.take();}//如果不为空if (f != null) {//自减 --active;try {//返回 这里如果获取异常下面做了处理return f.get();} catch (ExecutionException eex) {ee = eex;} catch (RuntimeException rex) {ee = new ExecutionException(rex);}}}//如果异常类型为空 进行初始化if (ee == null)ee = new ExecutionException();//然后抛出throw ee;} finally {//最后做下 所有任务的取消for (int i = 0, size = futures.size(); i < size; i++)futures.get(i).cancel(true);}}//调用以上的方法public  T invokeAny(Collection> tasks)throws InterruptedException, ExecutionException {try {return doInvokeAny(tasks, false, 0);} catch (TimeoutException cannotHappen) {assert false;return null;}}//带过期时间的调用任意一个任务public  T invokeAny(Collection> tasks,long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException {return doInvokeAny(tasks, true, unit.toNanos(timeout));}//调用所有任务public  List> invokeAll(Collection> tasks)throws InterruptedException {if (tasks == null)throw new NullPointerException();ArrayList> futures = new ArrayList>(tasks.size());boolean done = false;try {for (Callable t : tasks) {//注意这个RunnableFuture 是runnable和future的结合体,用于表示一个异步任务的结果RunnableFuture f = newTaskFor(t);futures.add(f);//执行execute(f);}for (int i = 0, size = futures.size(); i < size; i++) {Future f = futures.get(i);if (!f.isDone()) {try {f.get();} catch (CancellationException ignore) {} catch (ExecutionException ignore) {}}}done = true;return futures;} finally {if (!done)for (int i = 0, size = futures.size(); i < size; i++)futures.get(i).cancel(true);}}//带过期时间调用所有任务public  List> invokeAll(Collection> tasks,long timeout, TimeUnit unit)throws InterruptedException {if (tasks == null)throw new NullPointerException();long nanos = unit.toNanos(timeout);ArrayList> futures = new ArrayList>(tasks.size());boolean done = false;try {for (Callable t : tasks)futures.add(newTaskFor(t));final long deadline = System.nanoTime() + nanos;final int size = futures.size();// Interleave time checks and calls to execute in case// executor doesn't have any/much parallelism.for (int i = 0; i < size; i++) {execute((Runnable)futures.get(i));nanos = deadline - System.nanoTime();if (nanos <= 0L)return futures;}for (int i = 0; i < size; i++) {Future f = futures.get(i);if (!f.isDone()) {if (nanos <= 0L)return futures;try {f.get(nanos, TimeUnit.NANOSECONDS);} catch (CancellationException ignore) {} catch (ExecutionException ignore) {} catch (TimeoutException toe) {return futures;}nanos = deadline - System.nanoTime();}}done = true;return futures;} finally {if (!done)for (int i = 0, size = futures.size(); i < size; i++)futures.get(i).cancel(true);}}}

AbstractExecutorService中提供的方法实现包括以下几个方面:

  1. newTaskFor()方法:该方法用于创建一个RunnableFuture对象,它是Future和Runnable的结合体,可以用于表示一个异步任务的执行结果。在AbstractExecutorService中,该方法的默认实现是使用FutureTask类创建一个RunnableFuture对象,如果需要使用其它实现,可以在子类中重写该方法。

  2. submit()方法:该方法是ExecutorService接口中定义的方法,用于提交一个任务给线程池执行。在AbstractExecutorService中,提供了Runnable和Callable两种类型的任务提交方法,它们都是调用newTaskFor()方法创建一个RunnableFuture对象,并将其交给execute()方法执行。如果需要实现自定义的任务提交逻辑,可以在子类中重写该方法。需要注意的是,AbstractExecutorService是一个抽象类,不能直接使用,需要通过继承该类并实现其它方法来实现自定义的线程池。

java.util.concurrent.FutureTask

这个是一个核心类。

state状态说明:

  1. NEW:初始状态,表示FutureTask对象已经创建,但任务还没有开始执行。

  2. COMPLETING:表示任务已经执行完成,但还没有将结果设置到FutureTask中。

  3. NORMAL:表示任务执行成功,并且已经将结果设置到FutureTask中。

  4. EXCEPTIONAL:表示任务执行过程中抛出了异常,并且已经将异常信息设置到FutureTask中。

  5. CANCELLED:表示任务已经被取消。

  6. INTERRUPTING:表示任务正在被中断。

  7. INTERRUPTED:表示任务已经被中断。

package java.util.concurrent;
import java.util.concurrent.locks.LockSupport;
//一个可取消的异步计算。
//这里要注意一下,这个是实现了RunnableFuture 而RunnableFuture是 继承了:Runnable, Future
public class FutureTask implements RunnableFuture {/*** The run state of this task, initially NEW. The run state* transitions to a terminal state only in methods set,* setException, and cancel. During completion, state may take on* transient values of COMPLETING (while outcome is being set) or* INTERRUPTING (only while interrupting the runner to satisfy a* cancel(true)). Transitions from these intermediate to final* states use cheaper ordered/lazy writes because values are unique* and cannot be further modified.** Possible state transitions:* NEW -> COMPLETING -> NORMAL* NEW -> COMPLETING -> EXCEPTIONAL* NEW -> CANCELLED* NEW -> INTERRUPTING -> INTERRUPTED*///状态 可能的状态转换:NEW -> completion -> NORMAL NEW -> completion -> exception NEW -> CANCELLED NEW -> INTERRUPTED -> INTERRUPTEDprivate volatile int state;//实始化状态private static final int NEW = 0;/**
NEW:初始状态,表示FutureTask对象已经创建,但任务还没有开始执行。
COMPLETING:表示任务已经执行完成,但还没有将结果设置到FutureTask中。
NORMAL:表示任务执行成功,并且已经将结果设置到FutureTask中。
EXCEPTIONAL:表示任务执行过程中抛出了异常,并且已经将异常信息设置到FutureTask中。
CANCELLED:表示任务已经被取消。
INTERRUPTING:表示任务正在被中断。
INTERRUPTED:表示任务已经被中断。**/private static final int COMPLETING = 1;private static final int NORMAL = 2;private static final int EXCEPTIONAL = 3;private static final int CANCELLED = 4;private static final int INTERRUPTING = 5;private static final int INTERRUPTED = 6;/** 调用的对象 ,运行后为空 */private Callable callable;/**要返回的结果或跑出的异常 */private Object outcome; // non-volatile, protected by state reads/writes/** 运行可调用对象的线程;在run()期间进行case */private volatile Thread runner;/** 等待线程的Treiber堆栈 */private volatile WaitNode waiters;//返回已完成任务的结果或抛出异常。完成状态值@SuppressWarnings("unchecked")private V report(int s) throws ExecutionException {Object x = outcome;if (s == NORMAL)return (V)x;if (s >= CANCELLED)throw new CancellationException();throw new ExecutionException((Throwable)x);}//构造方法public FutureTask(Callable callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW; // ensure visibility of callable}//构造方法public FutureTask(Runnable runnable, V result) {this.callable = Executors.callable(runnable, result);this.state = NEW; // ensure visibility of callable}//判断是否取消public boolean isCancelled() {return state >= CANCELLED;}//判断是否已完成public boolean isDone() {return state != NEW;}//取消方法public boolean cancel(boolean mayInterruptIfRunning) {//状态不为初始 且if (!(state == NEW && cas锁获取成功 返回 falseUNSAFE.compareAndSwapInt(this, stateOffset, NEW,mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))return false;try { // in case call to interrupt throws exceptionif (mayInterruptIfRunning) {try {Thread t = runner;//不为空进行中断if (t != null)t.interrupt();} finally { // final state//更新状态UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);}}} finally {//删除并通知所有等待线程,调用done(),并空出可调用对象。finishCompletion();}//返回成功return true;}//获取线程public V get() throws InterruptedException, ExecutionException {int s = state;if (s <= COMPLETING)s = awaitDone(false, 0L);return report(s);}//带超时时间 获取public V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException {if (unit == null)throw new NullPointerException();int s = state;if (s <= COMPLETING &&(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)throw new TimeoutException();return report(s);}///重写方法protected void done() { }//设置结果为指定值protected void set(V v) {if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {outcome = v;UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final statefinishCompletion();}}//设置结果 出异常protected void setException(Throwable t) {if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {outcome = t;UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final statefinishCompletion();}}//运行方法public void run() {if (state != NEW ||!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))return;try {Callable c = callable;if (c != null && state == NEW) {V result;boolean ran;try {result = c.call();ran = true;} catch (Throwable ex) {result = null;ran = false;setException(ex);}if (ran)set(result);}} finally {// runner must be non-null until state is settled to// prevent concurrent calls to run()runner = null;// state must be re-read after nulling runner to prevent// leaked interruptsint s = state;if (s >= INTERRUPTING)handlePossibleCancellationInterrupt(s);}}//执行不进行设置结果protected boolean runAndReset() {if (state != NEW ||!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))return false;boolean ran = false;int s = state;try {Callable c = callable;if (c != null && s == NEW) {try {c.call(); // don't set resultran = true;} catch (Throwable ex) {setException(ex);}}} finally {// runner must be non-null until state is settled to// prevent concurrent calls to run()runner = null;// state must be re-read after nulling runner to prevent// leaked interruptss = state;if (s >= INTERRUPTING)handlePossibleCancellationInterrupt(s);}return ran && s == NEW;}//确保任何来自可能的取消(true)的中断只在运行或runAndReset时传递给任务。private void handlePossibleCancellationInterrupt(int s) {// It is possible for our interrupter to stall before getting a// chance to interrupt us. Let's spin-wait patiently.if (s == INTERRUPTING)while (state == INTERRUPTING)Thread.yield(); // wait out pending interrupt// assert state == INTERRUPTED;// We want to clear any interrupt we may have received from// cancel(true). However, it is permissible to use interrupts// as an independent mechanism for a task to communicate with// its caller, and there is no way to clear only the// cancellation interrupt.//// Thread.interrupted();}//在Treiber堆栈中记录等待线程的简单链表节点。static final class WaitNode {volatile Thread thread;volatile WaitNode next;WaitNode() { thread = Thread.currentThread(); }}//删除并通知所有等待线程,调用done(),并空出可调用对象。private void finishCompletion() {// assert state > COMPLETING;for (WaitNode q; (q = waiters) != null;) {if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {for (;;) {Thread t = q.thread;if (t != null) {q.thread = null;LockSupport.unpark(t);}WaitNode next = q.next;if (next == null)break;q.next = null; // unlink to help gcq = next;}break;}}done();callable = null; // to reduce footprint}//在中断或超时时等待完成或中止private int awaitDone(boolean timed, long nanos)throws InterruptedException {final long deadline = timed ? System.nanoTime() + nanos : 0L;WaitNode q = null;boolean queued = false;for (;;) {if (Thread.interrupted()) {removeWaiter(q);throw new InterruptedException();}int s = state;if (s > COMPLETING) {if (q != null)q.thread = null;return s;}else if (s == COMPLETING) // cannot time out yetThread.yield();else if (q == null)q = new WaitNode();else if (!queued)queued = UNSAFE.compareAndSwapObject(this, waitersOffset,q.next = waiters, q);else if (timed) {nanos = deadline - System.nanoTime();if (nanos <= 0L) {removeWaiter(q);return state;}LockSupport.parkNanos(this, nanos);}elseLockSupport.park(this);}}//尝试断开超时或中断的等待节点的链接,以避免累积垃圾。private void removeWaiter(WaitNode node) {if (node != null) {node.thread = null;retry:for (;;) { // restart on removeWaiter racefor (WaitNode pred = null, q = waiters, s; q != null; q = s) {s = q.next;if (q.thread != null)pred = q;else if (pred != null) {pred.next = s;if (pred.thread == null) // check for racecontinue retry;}else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,q, s))continue retry;}break;}}}//已下是初始化的信息// Unsafe mechanicsprivate static final sun.misc.Unsafe UNSAFE;private static final long stateOffset;private static final long runnerOffset;private static final long waitersOffset;static {try {UNSAFE = sun.misc.Unsafe.getUnsafe();Class k = FutureTask.class;stateOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("state"));runnerOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("runner"));waitersOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("waiters"));} catch (Exception e) {throw new Error(e);}}}

java.util.concurrent.ThreadPoolExecutor

这个就是主类的学习了,核心的线程池实现。

package java.util.concurrent;import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.*;
//一种执行程序服务,它使用可能有多个池化线程之一执行每个提交的任务,通常使用执行程序工厂方法进行配置。
//线程池解决了两个不同的问题:由于减少了每个任务的调用开销,它们通常在执行大量异步任务时提供改进的性能,并且它们提供了一种绑定和管理执行任务集合时消耗的资源(包括线程)的方法。
public class ThreadPoolExecutor extends AbstractExecutorService {//主池控制状态 ctl,是一个原子整数,包含两个概念字段 workerCount,指示线程运行状态的有效数量,指示是否正在运行、关闭等 为了将它们打包到一个 int 中,我们将 workerCount 限制为 (2^29)-1(约 5 亿)线程,而不是 (2^31)-1(20 亿)否则可表示。/* 相关方法:runStateOf:获取运行状态;workerCountOf:获取活动线程数;ctlOf:获取运行状态和活动线程数的值。*/private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));private static final int COUNT_BITS = Integer.SIZE - 3;private static final int CAPACITY = (1 << COUNT_BITS) - 1;//以下是高位的状态//高3位为111 线程池正在运行,可以接受新的任务。以及对已添加的任务进行处理。private static final int RUNNING = -1 << COUNT_BITS;//高3位为000 线程池正在关闭,不再接受新的任务,但会继续处理已经提交的任务。private static final int SHUTDOWN = 0 << COUNT_BITS;//高3位为001 线程池已经停止,不再接受新的任务,也不会处理已经提交的任务,并且会中断正在执行的任务。private static final int STOP = 1 << COUNT_BITS;//高3位为010 所有的任务都已经终止,线程数量为 0,即将进入 TERMINATED 状态。private static final int TIDYING = 2 << COUNT_BITS;//高3位为011 线程池已经终止,不再接受新的任务。private static final int TERMINATED = 3 << COUNT_BITS;// Packing and unpacking ctl//获取运行状态private static int runStateOf(int c)     { return c & ~CAPACITY; }//获取活动线程数private static int workerCountOf(int c)  { return c & CAPACITY; }//获取运行状态和活动线程数的值private static int ctlOf(int rs, int wc) { return rs | wc; }//用于判断 c是否小于s 一般用于状态判断private static boolean runStateLessThan(int c, int s) {return c < s;}//用于判断 c大于等于sprivate static boolean runStateAtLeast(int c, int s) {return c >= s;}//判断是否正在运行private static boolean isRunning(int c) {return c < SHUTDOWN;}//cas方式进行状态递增private boolean compareAndIncrementWorkerCount(int expect) {return ctl.compareAndSet(expect, expect + 1);}//cas方式状态递减private boolean compareAndDecrementWorkerCount(int expect) {return ctl.compareAndSet(expect, expect - 1);}//用于线程突然中断调用private void decrementWorkerCount() {do {} while (! compareAndDecrementWorkerCount(ctl.get()));}//用于保存任务和移交给工作线程的队列。private final BlockingQueue workQueue;//重入锁private final ReentrantLock mainLock = new ReentrantLock();/*** 线程池的工作线程集*/private final HashSet workers = new HashSet();/*** 等待终止的条件*/private final Condition termination = mainLock.newCondition();/*** 线程池曾经达到的最大线程数量*/private int largestPoolSize;/*** 已完成的任务数量*/private long completedTaskCount;//线程工厂,用于创建新的线程。private volatile ThreadFactory threadFactory;/*** 任务拒绝处理器,当工作队列已满且当前线程数等于最大线程数时,按照提交的任务拒绝策略来处理任务*/private volatile RejectedExecutionHandler handler;//线程空闲超时时间,当线程池中的线程数量大于核心线程数时,空闲线程保持活跃的时间。private volatile long keepAliveTime;/*** 如果为 false(默认值),则核心线程即使在空闲时也保持活动状态。如果为 true,则核心线程使用 keepAliveTime 来超时等待工作。*/private volatile boolean allowCoreThreadTimeOut;/*** 线程池核心线程数量,即使线程处于空闲状态,也不会被回收。*/private volatile int corePoolSize;/*** 线程池最大线程数量,当工作队列已满且当前线程数小于最大线程数时,会创建新的线程来处理任务。*/private volatile int maximumPoolSize;/*** 默认的拒绝策略*/private static final RejectedExecutionHandler defaultHandler =new AbortPolicy();/*** 关闭和关闭现在的调用方所需的权限。*/private static final RuntimePermission shutdownPerm =new RuntimePermission("modifyThread");/*执行终结器时要使用的上下文 */private final AccessControlContext acc;/*** Class Worker 主要维护运行任务的线程的中断控制状态,以及其他次要簿记。*/private final class Workerextends AbstractQueuedSynchronizerimplements Runnable{/*** This class will never be serialized, but we provide a* serialVersionUID to suppress a javac warning.*/private static final long serialVersionUID = 6138294804551838833L;/** 工作线程 */final Thread thread;/** 工作线程需要执行的第一个任务,通常是从工作队列中取出来的。默认为空 */Runnable firstTask;/** 线程的计数器*/volatile long completedTasks;/***构造方法*/Worker(Runnable firstTask) {//setState(-1); // 禁止中断this.firstTask = firstTask;//初始化一个工作线程this.thread = getThreadFactory().newThread(this);}/* 执行 */public void run() {runWorker(this);}// Lock methods//// The value 0 represents the unlocked state.// The value 1 represents the locked state.//判断是否已加锁 true为是 false 否protected boolean isHeldExclusively() {return getState() != 0;}//尝试获取锁protected boolean tryAcquire(int unused) {if (compareAndSetState(0, 1)) {setExclusiveOwnerThread(Thread.currentThread());return true;}return false;}//尝试释放锁protected boolean tryRelease(int unused) {setExclusiveOwnerThread(null);setState(0);return true;}//加锁public void lock()        { acquire(1); }//尝试加锁public boolean tryLock()  { return tryAcquire(1); }//解锁public void unlock()      { release(1); }//判断是否锁住方法 true为是 false为否public boolean isLocked() { return isHeldExclusively(); }//中断方法void interruptIfStarted() {Thread t;if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {try {t.interrupt();} catch (SecurityException ignore) {}}}}/** Methods for setting control state*///转换指定状态private void advanceRunState(int targetState) {for (;;) {int c = ctl.get();if (runStateAtLeast(c, targetState) ||ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))break;}}//如果(关闭且池和队列为空)或(停止且池为空),则转换为终止状态。final void tryTerminate() {for (;;) {int c = ctl.get();//判断是否运行 或 结束状态 或 (关闭且死亡) 则直接返回if (isRunning(c) ||runStateAtLeast(c, TIDYING) ||(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))return;//非终止,则直接终止if (workerCountOf(c) != 0) { // Eligible to terminateinterruptIdleWorkers(ONLY_ONE);return;}//上锁(重入锁)final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {//cas锁if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {try {//中断terminated();} finally {//最终设置状态ctl.set(ctlOf(TERMINATED, 0));termination.signalAll();}return;}} finally {//解锁mainLock.unlock();}// else retry on failed CAS}}/** Methods for controlling interrupts to worker threads.*///如果有安全管理器,请确保调用方通常有权关闭线程private void checkShutdownAccess() {SecurityManager security = System.getSecurityManager();if (security != null) {security.checkPermission(shutdownPerm);final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {for (Worker w : workers)security.checkAccess(w.thread);} finally {mainLock.unlock();}}}/*** 中断所有线程方法*/private void interruptWorkers() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {for (Worker w : workers)w.interruptIfStarted();} finally {mainLock.unlock();}}/*** 中断可能正在等待任务的线程*/private void interruptIdleWorkers(boolean onlyOne) {//重入锁final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {for (Worker w : workers) {Thread t = w.thread;if (!t.isInterrupted() && w.tryLock()) {try {t.interrupt();} catch (SecurityException ignore) {} finally {w.unlock();}}if (onlyOne)break;}} finally {//解锁mainLock.unlock();}}//中断所有线程方法private void interruptIdleWorkers() {interruptIdleWorkers(false);}private static final boolean ONLY_ONE = true;/** Misc utilities, most of which are also exported to* ScheduledThreadPoolExecutor*//*** 调用给定命令的拒绝执行处理程序。*/final void reject(Runnable command) {handler.rejectedExecution(command, this);}/*** 关闭方法(空实现)*/void onShutdown() {}/*** 判断关机或启动的方法*/final boolean isRunningOrShutdown(boolean shutdownOK) {int rs = runStateOf(ctl.get());return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);}/**将任务挪到新表中*/private List drainQueue() {BlockingQueue q = workQueue;ArrayList taskList = new ArrayList();q.drainTo(taskList);if (!q.isEmpty()) {for (Runnable r : q.toArray(new Runnable[0])) {if (q.remove(r))taskList.add(r);}}return taskList;}/** Methods for creating, running and cleaning up after workers*//*** 检查是否可以根据当前池状态和给定边界(核心或最大)添加新工作线程。*/private boolean addWorker(Runnable firstTask, boolean core) {retry:for (;;) {int c = ctl.get();int rs = runStateOf(c);// Check if queue empty only if necessary.if (rs >= SHUTDOWN &&! (rs == SHUTDOWN &&firstTask == null &&! workQueue.isEmpty()))return false;for (;;) {int wc = workerCountOf(c);if (wc >= CAPACITY ||wc >= (core ? corePoolSize : maximumPoolSize))return false;if (compareAndIncrementWorkerCount(c))break retry;c = ctl.get(); // Re-read ctlif (runStateOf(c) != rs)continue retry;// else CAS failed due to workerCount change; retry inner loop}}boolean workerStarted = false;boolean workerAdded = false;Worker w = null;try {w = new Worker(firstTask);final Thread t = w.thread;if (t != null) {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {// Recheck while holding lock.// Back out on ThreadFactory failure or if// shut down before lock acquired.int rs = runStateOf(ctl.get());if (rs < SHUTDOWN ||(rs == SHUTDOWN && firstTask == null)) {if (t.isAlive()) // precheck that t is startablethrow new IllegalThreadStateException();workers.add(w);int s = workers.size();if (s > largestPoolSize)largestPoolSize = s;workerAdded = true;}} finally {mainLock.unlock();}if (workerAdded) {t.start();workerStarted = true;}}} finally {if (! workerStarted)addWorkerFailed(w);}return workerStarted;}/*** 用于工作线程回滚的方法*/private void addWorkerFailed(Worker w) {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {if (w != null)workers.remove(w);decrementWorkerCount();tryTerminate();} finally {mainLock.unlock();}}//从队列中删除线程private void processWorkerExit(Worker w, boolean completedAbruptly) {if (completedAbruptly) // If abrupt, then workerCount wasn't adjusteddecrementWorkerCount();final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {completedTaskCount += w.completedTasks;workers.remove(w);} finally {mainLock.unlock();}tryTerminate();int c = ctl.get();if (runStateLessThan(c, STOP)) {if (!completedAbruptly) {int min = allowCoreThreadTimeOut ? 0 : corePoolSize;if (min == 0 && ! workQueue.isEmpty())min = 1;if (workerCountOf(c) >= min)return; // replacement not needed}addWorker(null, false);}}//获取一个任务private Runnable getTask() {boolean timedOut = false; // Did the last poll() time out?for (;;) {int c = ctl.get();int rs = runStateOf(c);// Check if queue empty only if necessary.if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {decrementWorkerCount();return null;}int wc = workerCountOf(c);// Are workers subject to culling?boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;if ((wc > maximumPoolSize || (timed && timedOut))&& (wc > 1 || workQueue.isEmpty())) {if (compareAndDecrementWorkerCount(c))return null;continue;}try {Runnable r = timed ?workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :workQueue.take();if (r != null)return r;timedOut = true;} catch (InterruptedException retry) {timedOut = false;}}}/*** 主工作线程运行循环** 1.我们可能会从初始任务开始,在这种情况下,我们不需要获得第一个任务。** 2.在运行任何任务之前,获取锁以防止在执行任务时发生其他池中断,然后我们确保除非池停止,否则该线程没有设置其中断。** 3. Each task run is preceded by a call to beforeExecute, which* might throw an exception, in which case we cause thread to die* (breaking loop with completedAbruptly true) without processing* the task.** 4.任务完成进行收集任务的处理** 5. 任务执行完成后,调用 afterExecute,这也可能会抛出异常,这也会导致线程死亡。** The net effect of the exception mechanics is that afterExecute* and the thread's UncaughtExceptionHandler have as accurate* information as we can provide about any problems encountered by* user code.** @param w the worker*/final void runWorker(Worker w) {//获取当前线程Thread wt = Thread.currentThread();//获取第一个任务Runnable task = w.firstTask;w.firstTask = null;//解锁(允许中断)w.unlock(); // allow interrupts//最终退出使用boolean completedAbruptly = true;try {//循环从队列中获取一个线程while (task != null || (task = getTask()) != null) {//上锁w.lock();// If pool is stopping, ensure thread is interrupted;// if not, ensure thread is not interrupted. This// requires a recheck in second case to deal with// shutdownNow race while clearing interrupt//判断是需要中断if ((runStateAtLeast(ctl.get(), STOP) ||(Thread.interrupted() &&runStateAtLeast(ctl.get(), STOP))) &&!wt.isInterrupted())wt.interrupt();try {//执行task的方法beforeExecute(wt, task);Throwable thrown = null;try {//执行task.run();} catch (RuntimeException x) {thrown = x; throw x;} catch (Error x) {thrown = x; throw x;} catch (Throwable x) {thrown = x; throw new Error(x);} finally {afterExecute(task, thrown);}} finally {//当前线程赋为空task = null;//自动 并解锁w.completedTasks++;w.unlock();}}//全部执行完completedAbruptly = false;} finally {processWorkerExit(w, completedAbruptly);}}// Public constructors and methods//构造方法带参//corePoolSize 核心数//maximumPoolSize 最大线程数量//keepAliveTime 超时时间//TimeUnit 时间单位//BlockingQueue 执行队列任务public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);}//同上类似public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, defaultHandler);}//同上类似public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,RejectedExecutionHandler handler) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);}public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;}//提交执行任务(异步的)public void execute(Runnable command) {if (command == null)throw new NullPointerException();/***分 3 个步骤进行:1. 如果正在运行的线程少于 corePoolSize,尝试使用给定命令作为其第一个任务来启动新线程。对 addWorker 的调用以原子方式检查 runState 和 workerCount,通过返回 false 来防止错误警报,这些警报会在空闲添加线程。2. 如果一个任务可以成功排队,那么仍然需要仔细检查我们是否应该添加一个线程(因为现有线程自上次检查以来就死了)或者池在进入此方法后关闭了。重新检查状态,如有必要,如果停止,则回滚排队,如果没有,则启动一个新线程。3.如果不能排队任务,那么尝试添加一个新线程。如果失败了,要么是已经关闭或饱和,因此拒绝这项任务。Proceed in 3 steps:int c = ctl.get();if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command))reject(command);else if (workerCountOf(recheck) == 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);}//关闭线程池(无返回)public void shutdown() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {checkShutdownAccess();advanceRunState(SHUTDOWN);interruptIdleWorkers();onShutdown(); // hook for ScheduledThreadPoolExecutor} finally {mainLock.unlock();}tryTerminate();}//关闭线程池(并返回等待执行的任务的列表。)public List shutdownNow() {List tasks;//逻辑是上锁然后获取列表,最后返回final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {checkShutdownAccess();advanceRunState(STOP);interruptWorkers();tasks = drainQueue();} finally {mainLock.unlock();}tryTerminate();return tasks;}//判断当前是否关闭 true是 false否public boolean isShutdown() {return ! isRunning(ctl.get());}//判断是否未完全停止(正在关机中)public boolean isTerminating() {int c = ctl.get();return ! isRunning(c) && runStateLessThan(c, TERMINATED);}//判断线程是否已终止public boolean isTerminated() {return runStateAtLeast(ctl.get(), TERMINATED);}//带超时时间终止方法public boolean awaitTermination(long timeout, TimeUnit unit)throws InterruptedException {long nanos = unit.toNanos(timeout);final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {for (;;) {if (runStateAtLeast(ctl.get(), TERMINATED))return true;if (nanos <= 0)return false;nanos = termination.awaitNanos(nanos);}} finally {mainLock.unlock();}}//关闭方法protected void finalize() {SecurityManager sm = System.getSecurityManager();if (sm == null || acc == null) {shutdown();} else {PrivilegedAction pa = () -> { shutdown(); return null; };AccessController.doPrivileged(pa, acc);}}//设置用于创建新线程的线程工厂。public void setThreadFactory(ThreadFactory threadFactory) {if (threadFactory == null)throw new NullPointerException();this.threadFactory = threadFactory;}//获取线程工厂public ThreadFactory getThreadFactory() {return threadFactory;}//为不可执行的任务设置新的处理程序。public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {if (handler == null)throw new NullPointerException();this.handler = handler;}/*** 返回不可执行任务的当前处理程序。** @return the current handler* @see #setRejectedExecutionHandler(RejectedExecutionHandler)*/public RejectedExecutionHandler getRejectedExecutionHandler() {return handler;}/*** 设置线程的核心数。** @param corePoolSize the new core size* @throws IllegalArgumentException if {@code corePoolSize < 0}* @see #getCorePoolSize*/public void setCorePoolSize(int corePoolSize) {if (corePoolSize < 0)throw new IllegalArgumentException();int delta = corePoolSize - this.corePoolSize;this.corePoolSize = corePoolSize;if (workerCountOf(ctl.get()) > corePoolSize)interruptIdleWorkers();else if (delta > 0) {// We don't really know how many new threads are "needed".// As a heuristic, prestart enough new workers (up to new// core size) to handle the current number of tasks in// queue, but stop if queue becomes empty while doing so.int k = Math.min(delta, workQueue.size());while (k-- > 0 && addWorker(null, true)) {if (workQueue.isEmpty())break;}}}/*** Returns the core number of threads.** @return the core number of threads* @see #setCorePoolSize*/public int getCorePoolSize() {return corePoolSize;}/***启动核心线程,使其空闲等待工作。** @return {@code true} if a thread was started*/public boolean prestartCoreThread() {return workerCountOf(ctl.get()) < corePoolSize &&addWorker(null, true);}/*** Same as prestartCoreThread except arranges that at least one* thread is started even if corePoolSize is 0.*/void ensurePrestart() {int wc = workerCountOf(ctl.get());if (wc < corePoolSize)addWorker(null, true);else if (wc == 0)addWorker(null, false);}/*** 启动所有核心线程** @return the number of threads started*/public int prestartAllCoreThreads() {int n = 0;while (addWorker(null, true))++n;return n;}/*** 如果此线程池允许核心线程超时,则返回 true。如果 keepAlive 时间内没有任务到达,则返回 true如果需要,在新任务到达时替换。** @return {@code true} if core threads are allowed to time out,* else {@code false}** @since 1.6*/public boolean allowsCoreThreadTimeOut() {return allowCoreThreadTimeOut;}//同上类似public void allowCoreThreadTimeOut(boolean value) {if (value && keepAliveTime <= 0)throw new IllegalArgumentException("Core threads must have nonzero keep alive times");if (value != allowCoreThreadTimeOut) {allowCoreThreadTimeOut = value;if (value)interruptIdleWorkers();}}//设置最大的线程核心数public void setMaximumPoolSize(int maximumPoolSize) {if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)throw new IllegalArgumentException();this.maximumPoolSize = maximumPoolSize;if (workerCountOf(ctl.get()) > maximumPoolSize)interruptIdleWorkers();}/*** Returns the maximum allowed number of threads.** @return the maximum allowed number of threads* @see #setMaximumPoolSize*/public int getMaximumPoolSize() {return maximumPoolSize;}//设置线程空闲超时时间public void setKeepAliveTime(long time, TimeUnit unit) {if (time < 0)throw new IllegalArgumentException();if (time == 0 && allowsCoreThreadTimeOut())throw new IllegalArgumentException("Core threads must have nonzero keep alive times");long keepAliveTime = unit.toNanos(time);long delta = keepAliveTime - this.keepAliveTime;this.keepAliveTime = keepAliveTime;if (delta < 0)interruptIdleWorkers();}//获取空间时间(这个单位有点坑,没用到 )public long getKeepAliveTime(TimeUnit unit) {return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);}/* User-level queue utilities *///返回执行任务队列public BlockingQueue getQueue() {return workQueue;}//删除任务方法public boolean remove(Runnable task) {boolean removed = workQueue.remove(task);tryTerminate(); // In case SHUTDOWN and now emptyreturn removed;}//尝试从工作队列中删除所有已取消任务public void purge() {final BlockingQueue q = workQueue;try {Iterator it = q.iterator();//遍历查找while (it.hasNext()) {Runnable r = it.next();if (r instanceof Future && ((Future)r).isCancelled())it.remove();}} catch (ConcurrentModificationException fallThrough) {// Take slow path if we encounter interference during traversal.// Make copy for traversal and call remove for cancelled entries.// The slow path is more likely to be O(N*N).for (Object r : q.toArray())if (r instanceof Future && ((Future)r).isCancelled())q.remove(r);}tryTerminate(); // In case SHUTDOWN and now empty}/* Statistics *///返回池中的当前线程数。public int getPoolSize() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {// Remove rare and surprising possibility of// isTerminated() && getPoolSize() > 0return runStateAtLeast(ctl.get(), TIDYING) ? 0: workers.size();} finally {mainLock.unlock();}}//返回存活线程数public int getActiveCount() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {int n = 0;for (Worker w : workers)if (w.isLocked())++n;return n;} finally {mainLock.unlock();}}//返回最大线程数public int getLargestPoolSize() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {return largestPoolSize;} finally {mainLock.unlock();}}//返回当前任务数public long getTaskCount() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {long n = completedTaskCount;for (Worker w : workers) {n += w.completedTasks;if (w.isLocked())++n;}return n + workQueue.size();} finally {mainLock.unlock();}}//返回已完成执行的任务的大致总数。public long getCompletedTaskCount() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {long n = completedTaskCount;for (Worker w : workers)n += w.completedTasks;return n;} finally {mainLock.unlock();}}public String toString() {long ncompleted;int nworkers, nactive;final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {ncompleted = completedTaskCount;nactive = 0;nworkers = workers.size();for (Worker w : workers) {ncompleted += w.completedTasks;if (w.isLocked())++nactive;}} finally {mainLock.unlock();}int c = ctl.get();String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :(runStateAtLeast(c, TERMINATED) ? "Terminated" :"Shutting down"));return super.toString() +"[" + rs +", pool size = " + nworkers +", active threads = " + nactive +", queued tasks = " + workQueue.size() +", completed tasks = " + ncompleted +"]";}/* Extension hooks *//*** Method invoked prior to executing the given Runnable in the* given thread. This method is invoked by thread {@code t} that* will execute task {@code r}, and may be used to re-initialize* ThreadLocals, or to perform logging.** 

This implementation does nothing, but may be customized in* subclasses. Note: To properly nest multiple overridings, subclasses* should generally invoke {@code super.beforeExecute} at the end of* this method.** @param t the thread that will run task {@code r}* @param r the task that will be executed*/protected void beforeExecute(Thread t, Runnable r) { }/*** Method invoked upon completion of execution of the given Runnable.* This method is invoked by the thread that executed the task. If* non-null, the Throwable is the uncaught {@code RuntimeException}* or {@code Error} that caused execution to terminate abruptly.**

This implementation does nothing, but may be customized in* subclasses. Note: To properly nest multiple overridings, subclasses* should generally invoke {@code super.afterExecute} at the* beginning of this method.**

Note: When actions are enclosed in tasks (such as* {@link FutureTask}) either explicitly or via methods such as* {@code submit}, these task objects catch and maintain* computational exceptions, and so they do not cause abrupt* termination, and the internal exceptions are not* passed to this method. If you would like to trap both kinds of* failures in this method, you can further probe for such cases,* as in this sample subclass that prints either the direct cause* or the underlying exception if a task has been aborted:**

 {@code* class ExtendedExecutor extends ThreadPoolExecutor {* // ...* protected void afterExecute(Runnable r, Throwable t) {* super.afterExecute(r, t);* if (t == null && r instanceof Future) {* try {* Object result = ((Future) r).get();* } catch (CancellationException ce) {* t = ce;* } catch (ExecutionException ee) {* t = ee.getCause();* } catch (InterruptedException ie) {* Thread.currentThread().interrupt(); // ignore/reset* }* }* if (t != null)* System.out.println(t);* }* }}
** @param r the runnable that has completed* @param t the exception that caused termination, or null if* execution completed normally*/protected void afterExecute(Runnable r, Throwable t) { }/*** Method invoked when the Executor has terminated. Default* implementation does nothing. Note: To properly nest multiple* overridings, subclasses should generally invoke* {@code super.terminated} within this method.*/protected void terminated() { }/* Predefined RejectedExecutionHandlers *//*** A handler for rejected tasks that runs the rejected task* directly in the calling thread of the {@code execute} method,* unless the executor has been shut down, in which case the task* is discarded.*/public static class CallerRunsPolicy implements RejectedExecutionHandler {/*** Creates a {@code CallerRunsPolicy}.*/public CallerRunsPolicy() { }/*** Executes task r in the caller's thread, unless the executor* has been shut down, in which case the task is discarded.** @param r the runnable task requested to be executed* @param e the executor attempting to execute this task*/public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {if (!e.isShutdown()) {r.run();}}}/*** 拒绝任务的处理程序,该处理程序引发* {@code RejectedExecutionException}.*/public static class AbortPolicy implements RejectedExecutionHandler {/*** Creates an {@code AbortPolicy}.*/public AbortPolicy() { }/*** Always throws RejectedExecutionException.** @param r the runnable task requested to be executed* @param e the executor attempting to execute this task* @throws RejectedExecutionException always*/public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {throw new RejectedExecutionException("Task " + r.toString() +" rejected from " +e.toString());}}/*** 以静默方式丢弃被拒绝的任务的处理程序。*/public static class DiscardPolicy implements RejectedExecutionHandler {/*** Creates a {@code DiscardPolicy}.*/public DiscardPolicy() { }/*** Does nothing, which has the effect of discarding task r.** @param r the runnable task requested to be executed* @param e the executor attempting to execute this task*/public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {}}/*** 被拒绝任务的处理程序,它丢弃最早的未处理请求,*/public static class DiscardOldestPolicy implements RejectedExecutionHandler {/*** Creates a {@code DiscardOldestPolicy} for the given executor.*/public DiscardOldestPolicy() { }/*** Obtains and ignores the next task that the executor* would otherwise execute, if one is immediately available,* and then retries execution of task r, unless the executor* is shut down, in which case task r is instead discarded.** @param r the runnable task requested to be executed* @param e the executor attempting to execute this task*/public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {if (!e.isShutdown()) {e.getQueue().poll();e.execute(r);}}} }

线程池原理

fd4f796f7d1151c83a24799d60cee4b9.png

执行流程:

  • 当执行任务数<核心线程数量(corePoolSize),则创建一个新线程来执行。

  • 当执行任务数>=核心线程数量(corePoolSize),线程池内的阻塞队列未满,则将任务添加到该阻塞队列中;

  • 当执行任务数>=核心线程数量(corePoolSize)且 当执行任务数<线程池最大线程数量,线程池内的阻塞阶列已满,创建新线程来执行;

  • 当执行任务数>=核心线程数量(corePoolSize),线程池内的阻塞阶列已满,则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。

execute的执行流程:

b2766ba115f1424c2f16447efd9495f9.png

最后

    如果系统中有很多的线程要使用建议使用线程池,避免因为手动new的线程导致系统一些不稳定性因素出现,特别可以利用线程池来管理和保障系统的稳定性,当然具体怎么调,建议参考《阿里巴巴开发手册》。

本文仅写了ThreadPoolExecutor有部分源码没有深入去写注释,有需要详细的同学可再深入或私下交流。

参考文献

    https://zhuanlan.zhihu.com/p/505594640

相关内容

热门资讯

如果你总是焦虑,就读读这本书 ... 作者 | 暖葵向北来源 | 帆书 原樊登读书(ID:readingclub_btfx)知乎上有人问:...
新消费周报 | 美团京东启动万... 《CBNData新消费周报》精选本周新消费领域最新动态,公司头条、消费风向、营销动态、可持续消费一文...
美股正经历前所未有的变化 缇庤... 2025.07.26本文字数:3131,阅读时长大约6分钟来源 |玉渊谭天最近,和一位做全球资产配置...
世荣兆业向前老板跨国索赔28亿... 7月24日,A股上市公司世荣兆业(002016.SZ)公告称,公司就原董事长梁家荣侵犯公司权利的行为...
“淡水鱼第一股”大湖股份白酒业... 本文来源:时代周报 作者:幸雯雯 图源:图虫创意7月24日,被誉为“淡水鱼第一股”的大湖股份(60...
写45万网文爆料华熙生物财务造... 红星资本局7月26日消息,对于华熙生物发声明一事,当事人David告诉红星资本局,今天,“玻尿酸女王...
原创 哦... 这周五晚上,湖南卫视的“歌手”节目即将迎来第10轮的精彩比拼,单依纯的曲目选择再一次成为了大家热议的...
中国儒意如何消化万达“弃子” ... 万达的又一笔资产迎来新的归属。日前,中国儒意披露全资附属公司上海儒意星辰企业管理已与万达集团旗下的上...
中国驻柬埔寨大使馆:再次提醒柬... 每经AI快讯,7月26日,据中国驻柬埔寨大使馆公众号消息,7月24日,柬泰两国军队在奥多棉吉省、柏威...
泰方否认泰柬曾就停火达成一致!... 当地时间7月26日,泰国总理府发言人吉拉育否认了柬埔寨首相洪玛奈关于泰柬此前曾就停火达成一致的说法,...