@Test
public void test12() throws InterruptedException { 先做一个单元测试
CompletableFuture.runAsync(()->{ //在此处打断点
System.out.println("111");
});
Thread.sleep(400000);
}
一步一步把代码贴出来,看官看*好。
public static CompletableFuture runAsync(Runnable runnable) { //运行线程的方法
return asyncRunStage(asyncPool, runnable);
}
asyncPool是什么?看一下这个值的设置。
private static final Executor asyncPool = useCommonPool ?
ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
useCommonPool是什么?
private static final boolean useCommonPool =
(ForkJoinPool.getCommonPoolParallelism() > 1);
public static int getCommonPoolParallelism() {
return commonParallelism;
}
commonParallelism就是那个并发的线程数,它又是怎么来的呢?
static {
// initialize field offsets for CAS etc
。。。。。。
commonMaxSpares = DEFAULT_COMMON_MAX_SPARES;
defaultForkJoinWorkerThreadFactory =
new DefaultForkJoinWorkerThreadFactory();
modifyThreadPermission = new RuntimePermission("modifyThread");
common = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction() {
public ForkJoinPool run() { return makeCommonPool(); }}); //重点看makeCommonPool方法
int par = common.config & SMASK; // 获取到par SMASK的值是 65535 也就是1111111111111111 &操作还是common.config本身,看样子还是要看看config是怎么来的
commonParallelism = par > 0 ? par : 1; 想知道par是什么值,这个值为负数默认是1
}
private static ForkJoinPool makeCommonPool() {
int parallelism = -1; //这个并发的线程数默认是-1
ForkJoinWorkerThreadFactory factory = null;
。。。。。。
if (parallelism < 0 &&
(parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0) //看到了吧,线程池中的处理线程数=电脑核数-1
parallelism = 1;
if (parallelism > MAX_CAP)
parallelism = MAX_CAP;
return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE,
"ForkJoinPool.commonPool-worker-"); //指定线程的名字
}
1.ForkJoinPool将运行线程的最大数量限制为32767。尝试创建大于最大数目的池会导致{@code IllegalArgumentException}。
这个实现只在池关闭或者内部资源耗尽的时候才拒绝提交任务。通过抛出RejectedExecutionException异常。--就是说任务队列无限大, 拒绝策略就是一直可以接收任务.
2.CompletableFuture默认使用的线程池是 ForkJoinPool.commonPool(),commonPool是当前 JVM(进程) 上的所有 CompletableFuture、并行 Stream 共享的.
3.如果你cpu核数-1大于1,也就是你的cpu是小于等于两核,那么默认线程池会直接退化为 ThreadPerTaskExecutor,每个任务新开一个线程。
4.如果你的cpu核数大于2,那么池内的核心线程数就是cpu核数-1, 比如你的核心数是4核的,那么会使用默认的线程池ForkJoinPool,池内的核心线程数为3.
大家在用CompletableFuture时,要用自己定义的线程池来代替默认的线程池 ForkJoinPool.commonPool().因为ForkJoinPool.commonPool()仅适合cpu密集型任务,不适合io密集型任务.
如果服务是cpu密集型的,设置为电脑的核数
如果服务是io密集型的,设置为电脑的核数*2