什么是线程?
一个应用程序为一个进程(也有多个的),一个进程拥有至少1个线程,线程是这个进程所私有的,当进程结束时,线程会随着结束。如下图
当然更有一些内存相关的,这里不再过多深入,仅了解基础,不懂的同学自行搜索。
线程有哪些生命状态,怎么切换的?
NEW,新建
RUNNABLE,运行
BLOCKED,阻塞
WAITING,等待
TIMED_WAITING,超时等待
TERMINATED,终结
注意:java原生包不支持协程,需要支持可以引入第三方的quasar
java线程池有哪些?
线程池的主要作用是用来管理线程的一个容器,通过这个可以减少线程被无限制的创建和释放,导致系统资源无法很好管控,通过线程池可以通过分配、调优以及监控。
FixedThreadPool:固定大小的线程池,创建时指定线程数量,任务队列为无界队列。
CachedThreadPool:缓存线程池,线程数量不固定,会根据需要自动创建新线程,空闲线程会被保留60秒,任务队列为SynchronousQueue。
ScheduledThreadPool:定时器线程池,支持延时执行和定时周期执行任务。
SingleThreadExecutor:单线程线程池,只有一个线程执行任务,任务队列为无界队列。
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;
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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-7
Process finished with exit code 0
注意这里同等配置,在苹果M1没压力,在windows CPU 8核的CPU飙高100%~
为什么要用线程池而不用Thread?
这个问题对于老手来说是废话,对于新手来说就要注意了。首先我不否认说直接用Thread不好,一切还是要看你的场景,如果你的整个系统只有一或几处thread,并且执行都是很短时间及次数很少,当然我不否认这样也是没有问题,但是如果你有以下的情况就要注意了。
1.执行次数非常频繁;
2.执行的地点非常多;
3.执行的线程时间长度不可预知或很长;
那么可能出现如下的情况:
1.CPU或内存忽高忽地,大半夜默名奇妙有告警;
2.经常不知道为什么FullGc;
3.代码耦合不敢乱改;
4.出现很多不可控因素,比如内存一直被占着,线程数量太高,系统卡顿 当然还有很多~
...
所以说线程池 统一管控(分配、调优、监控)资源 一定程度保障系统的稳定性,几大点如下:
资源控制:线程池可以限制同时运行的线程数量,防止过度消耗系统资源和导致系统崩溃。
提高效率:线程池可以重复利用已创建的线程,避免了频繁创建和销毁线程的开销,提高了程序的执行效率。
提高响应速度:线程池可以预先创建并初始化一定数量的线程,当任务到来时,可以立即执行,提高了程序的响应速度。
简化编程:使用线程池可以让程序员专注于业务逻辑的实现,而不必关心线程的创建和管理,简化了编程过程。使用线程池可以更好地控制系统资源、提高程序的效率和响应速度,并且简化编程过程。因此,在多线程编程中,使用线程池是一种更加优秀的选择。
源码学习
Executor框架
Executor框架是Java中用于管理线程池的框架,它提供了一种将任务提交和执行分离的机制,使得线程的创建和销毁可以由框架自动管理,从而减少了线程创建和上下文切换的开销,提高了系统的性能。Executor框架主要包含以下三个核心组件:
Executor 接口:该接口定义了一个execute方法,用于将任务提交给线程池执行。
ExecutorService 接口:该接口继承了Executor接口,并增加了一些管理线程池的方法,例如submit方法、shutdown方法等。
ThreadPoolExecutor 类:该类是线程池的实现类,它提供了丰富的参数配置,可以根据不同的需求创建不同的线程池。例如,可以设置核心线程数、最大线程数、队列容量、拒绝策略等参数。使用Executor框架可以方便地实现线程池的创建和管理,提高系统的性能和稳定性。同时,Executor框架还提供了一些方便的工具类,例如Executors类、ScheduledExecutorService接口等,可以实现定时任务、延时任务、周期性任务等功能,非常适合于多线程编程和并发处理。
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<Runnable> shutdownNow();
/**
* isShutdown方法用于判断线程池是否已经关闭。
*/
boolean isShutdown();
/**
* isTerminated方法用于判断线程池是否已经关闭,并且所有任务都已经执行完毕。
*/
boolean isTerminated();
/**
* awaitTermination方法用于等待线程池关闭,并且所有任务都已经执行完毕。
*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
/**
* submit方法用于提交一个Callable或Runnable任务到线程池,并返回一个Future对象,可以通过Future对象获取任务的执行结果或取消任务的执行。
*/
<T> Future<T> submit(Callable<T> task);
/**
* Submits提交一个可运行任务以供执行,并返回表示该任务的Future。Future的get方法将在成功完成时返回给定的结果。
*/
<T> Future<T> submit(Runnable task, T result);
/**
* 提交一个可运行任务以供执行,并返回表示该任务的Future。Future的get方法将在成功完成时返回null。
*/
Future<?> submit(Runnable task);
/**
* 执行给定的任务,在所有任务完成时返回包含它们的状态和结果的Futures列表。的未来。对于返回列表的每个元素,isDone都是true。
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
/**
* 带超时时间 同上类似
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
/**
* 执行给定的任务,如果有成功完成的任务,则返回成功完成的任务的结果(即,没有抛出异常)。在正常或异常返回时,未完成的任务将被取消。如果在执行此操作时修改了给定的集合,则此方法的结果是未定义的。
*/
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
/**
* 同上类似 带超时时间
*/
<T> T invokeAny(Collection<? extends Callable<T>> 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 <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
//同上
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
//任务提交
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
//创建RunnableFuture
RunnableFuture<Void> ftask = newTaskFor(task, null);
//执行
execute(ftask);
//返回
return ftask;
}
//任务提交
//task为任务
//result 为自定义返回结果
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
//任务提交的方法
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
/**
* 该方法是实现唤醒任意一个方法
*/
private <T> T doInvokeAny(Collection<? extends Callable<T>> 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<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
//这里一个
ExecutorCompletionService<T> ecs =
new ExecutorCompletionService<T>(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<? extends Callable<T>> it = tasks.iterator();
// Start one task for sure; the rest incrementally
//确定开始的任务
futures.add(ecs.submit(it.next()));
--ntasks;//递减
int active = 1;
//循环调用
for (;;) {
//获取队列的头,如果没有为null (阻塞队列)
Future<T> f = ecs.poll();
//为空
if (f == null) {
//如果大于0
if (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,如果没有则等待。
else
f = 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> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
try {
return doInvokeAny(tasks, false, 0);
} catch (TimeoutException cannotHappen) {
assert false;
return null;
}
}
//带过期时间的调用任意一个任务
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return doInvokeAny(tasks, true, unit.toNanos(timeout));
}
//调用所有任务
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
//注意这个RunnableFuture 是runnable和future的结合体,用于表示一个异步任务的结果
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
//执行
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> 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 <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
long nanos = unit.toNanos(timeout);
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> 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<T> 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中提供的方法实现包括以下几个方面:
newTaskFor()方法:该方法用于创建一个RunnableFuture对象,它是Future和Runnable的结合体,可以用于表示一个异步任务的执行结果。在AbstractExecutorService中,该方法的默认实现是使用FutureTask类创建一个RunnableFuture对象,如果需要使用其它实现,可以在子类中重写该方法。
submit()方法:该方法是ExecutorService接口中定义的方法,用于提交一个任务给线程池执行。在AbstractExecutorService中,提供了Runnable和Callable两种类型的任务提交方法,它们都是调用newTaskFor()方法创建一个RunnableFuture对象,并将其交给execute()方法执行。如果需要实现自定义的任务提交逻辑,可以在子类中重写该方法。需要注意的是,AbstractExecutorService是一个抽象类,不能直接使用,需要通过继承该类并实现其它方法来实现自定义的线程池。
java.util.concurrent.FutureTask
这个是一个核心类。
state状态说明:
NEW:初始状态,表示FutureTask对象已经创建,但任务还没有开始执行。
COMPLETING:表示任务已经执行完成,但还没有将结果设置到FutureTask中。
NORMAL:表示任务执行成功,并且已经将结果设置到FutureTask中。
EXCEPTIONAL:表示任务执行过程中抛出了异常,并且已经将异常信息设置到FutureTask中。
CANCELLED:表示任务已经被取消。
INTERRUPTING:表示任务正在被中断。
INTERRUPTED:表示任务已经被中断。
package java.util.concurrent;
import java.util.concurrent.locks.LockSupport;
//一个可取消的异步计算。
//这里要注意一下,这个是实现了RunnableFuture 而RunnableFuture是 继承了:Runnable, Future<V>
public class FutureTask<V> implements RunnableFuture<V> {
/**
* 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 -> INTERRUPTED
private 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<V> 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<V> 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锁获取成功 返回 false
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (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 state
finishCompletion();
}
}
//设置结果 出异常
protected void setException(Throwable t) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = t;
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion();
}
}
//运行方法
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> 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 interrupts
int 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<V> c = callable;
if (c != null && s == NEW) {
try {
c.call(); // don't set result
ran = 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 interrupts
s = 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 gc
q = 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 yet
Thread.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);
}
else
LockSupport.park(this);
}
}
//尝试断开超时或中断的等待节点的链接,以避免累积垃圾。
private void removeWaiter(WaitNode node) {
if (node != null) {
node.thread = null;
retry:
for (;;) { // restart on removeWaiter race
for (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 race
continue retry;
}
else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
q, s))
continue retry;
}
break;
}
}
}
//已下是初始化的信息
// Unsafe mechanics
private 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大于等于s
private 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<Runnable> workQueue;
//重入锁
private final ReentrantLock mainLock = new ReentrantLock();
/**
* 线程池的工作线程集
*/
private final HashSet<Worker> workers = new HashSet<Worker>();
/**
* 等待终止的条件
*/
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 Worker
extends AbstractQueuedSynchronizer
implements 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 terminate
interruptIdleWorkers(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<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
ArrayList<Runnable> taskList = new ArrayList<Runnable>();
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 ctl
if (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 startable
throw 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 adjusted
decrementWorkerCount();
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<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
//同上类似
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
//同上类似
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> 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<Runnable> shutdownNow() {
List<Runnable> 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<Void> 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<Runnable> getQueue() {
return workQueue;
}
//删除任务方法
public boolean remove(Runnable task) {
boolean removed = workQueue.remove(task);
tryTerminate(); // In case SHUTDOWN and now empty
return removed;
}
//尝试从工作队列中删除所有已取消任务
public void purge() {
final BlockingQueue<Runnable> q = workQueue;
try {
Iterator<Runnable> 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() > 0
return 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.
*
* <p>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.
*
* <p>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.
*
* <p><b>Note:</b> 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 <em>not</em>
* 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:
*
* <pre> {@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);
* }
* }}</pre>
*
* @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);
}
}
}
}
线程池原理
执行流程:
当执行任务数<核心线程数量(corePoolSize),则创建一个新线程来执行。
当执行任务数>=核心线程数量(corePoolSize),线程池内的阻塞队列未满,则将任务添加到该阻塞队列中;
当执行任务数>=核心线程数量(corePoolSize)且 当执行任务数<线程池最大线程数量,线程池内的阻塞阶列已满,创建新线程来执行;
当执行任务数>=核心线程数量(corePoolSize),线程池内的阻塞阶列已满,则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。
execute的执行流程:
最后
如果系统中有很多的线程要使用建议使用线程池,避免因为手动new的线程导致系统一些不稳定性因素出现,特别可以利用线程池来管理和保障系统的稳定性,当然具体怎么调,建议参考《阿里巴巴开发手册》。
本文仅写了ThreadPoolExecutor有部分源码没有深入去写注释,有需要详细的同学可再深入或私下交流。
参考文献
https://zhuanlan.zhihu.com/p/505594640