优化策略
- 合理配置线程池:
- 理论依据:高并发场景下,使用默认的ForkJoinPool可能无法满足业务需求。通过自定义线程池,可以根据系统资源(如CPU核心数、内存等)和业务特性(如I/O密集型或CPU密集型任务)来合理分配线程资源,避免线程过多导致的上下文切换开销和资源竞争。对于CPU密集型任务,线程数一般设置为CPU核心数 + 1;对于I/O密集型任务,线程数可以设置得更高,如CPU核心数 * 2等,具体数值需通过性能测试确定。
- 代码示例:
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class CompletableFutureOptimization {
private static final int CPU_CORES = Runtime.getRuntime().availableProcessors();
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
CPU_CORES * 2,
CPU_CORES * 2,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1000),
new ThreadFactory() {
private final AtomicInteger threadNumber = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "Custom-Thread-" + threadNumber.getAndIncrement());
thread.setDaemon(false);
return thread;
}
},
new ThreadPoolExecutor.CallerRunsPolicy());
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
// 模拟一些计算
return "result";
}, executor)
.thenRun(() -> {
// 后续任务
System.out.println("任务完成后的操作");
}, executor);
}
}
- 优化任务编排方式:
- 理论依据:减少不必要的依赖和链式调用。如果任务之间的依赖关系复杂,可以将任务拆分成更细粒度的独立任务,并行执行,然后通过
CompletableFuture.allOf
等方法进行合并,这样可以充分利用多核CPU的性能,提高整体的执行效率。
- 代码示例:
import java.util.concurrent.*;
public class TaskOrchestrationOptimization {
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors() * 2,
Runtime.getRuntime().availableProcessors() * 2,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1000));
public static void main(String[] args) {
CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
// 模拟任务1
return "task1 result";
}, executor);
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> {
// 模拟任务2
return "task2 result";
}, executor);
CompletableFuture<Void> combinedTask = CompletableFuture.allOf(task1, task2);
combinedTask.thenRun(() -> {
try {
System.out.println("任务1结果: " + task1.get());
System.out.println("任务2结果: " + task2.get());
System.out.println("所有任务完成后的操作");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}, executor);
}
}
- 避免在
thenRun
中执行长时间操作:
- 理论依据:
thenRun
方法通常用于执行一些轻量级的后续操作。如果在thenRun
中执行长时间的计算或I/O操作,会阻塞线程,影响整个系统的并发性能。应该将长时间操作拆分出来,使用异步方式执行。
- 代码示例:
import java.util.concurrent.*;
public class AvoidLongRunningInThenRun {
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors() * 2,
Runtime.getRuntime().availableProcessors() * 2,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1000));
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
// 前置任务
return "前置任务结果";
}, executor)
.thenRun(() -> {
// 轻量级后续操作
System.out.println("轻量级后续操作");
}, executor)
.thenRunAsync(() -> {
// 长时间操作,使用异步方式
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("长时间异步操作完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, executor);
}
}