只要我在池中为 ForkJoinPool 提供一个额外的线程,它的执行速度与 ExecutorService 一样快。以下是使用的三个类:Main、RunnableTask 和 ForkJoinTask。在 16 核盒子上运行,程序每次输出如下: 执行时间:5002 ForkJoin 时间:5002
主类:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
public class Main {
public static void main(String[] args) throws InterruptedException {
runExecutor(80);
runForkJoin(80);
}
public static void runForkJoin(int size) {
ForkJoinPool fjp = new ForkJoinPool(17);
long start = System.currentTimeMillis();
fjp.invoke(new ForkJoinTask(size));
System.out.println("ForkJoin Time: "
+ (System.currentTimeMillis() - start));
fjp.shutdown();
}
public static void runExecutor(int size) throws InterruptedException {
ExecutorService exec = Executors.newFixedThreadPool(16);
CountDownLatch latch = new CountDownLatch(size);
long start = System.currentTimeMillis();
for (int i = 0; i < latch.getCount(); i++) {
exec.submit(new RunnableTask(latch));
}
latch.await();
System.out.println("Executor Time: "
+ (System.currentTimeMillis() - start));
exec.shutdown();
}
}
可运行类:
import java.util.concurrent.CountDownLatch;
public class RunnableTask implements Runnable {
private CountDownLatch latch;
public RunnableTask(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
Thread.sleep(1000);
latch.countDown();
} catch (Exception e) {
}
}
}
RecursiveTask 类:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RecursiveTask;
public class ForkJoinTask extends RecursiveTask {
private List<RecursiveTask> tasks;
private int size;
public ForkJoinTask(int size) {
super();
this.tasks = new ArrayList<>();
this.size = size;
}
@Override
protected Object compute() {
for (int i = 0; i < size; i++) {
RecursiveTask task = new RecursiveTask() {
@Override
protected Object compute() {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
return null;
}
};
task.fork();
tasks.add(task);
}
for (RecursiveTask task : tasks) {
task.join();
}
return null;
}
}
最佳答案
您的个人任务可以使两者 ForkJoinPool
和 ExecutorService
运行得比现在更快,而且两者都不是一个应该比另一个有很大的优势。
原因是,如果单个计算任务是 Thread.sleep(1000) ,则该任务不需要 CPU 资源。您可以增加线程数以匹配您的作业大小 (80),并在略多于 1 秒的运行时间内完成 80 秒的“工作”,因为线程实际上不会竞争任何类型的资源。
至于 ForkJoinPool
和 ExecutorService
之间的比较,差异与您的测试用例无关,因为您的工作不会产生任何应该的结果进一步计算的输入( MapReduce 中的“减少”步骤)。所以对你来说,它们都只是具有不同 API 的线程池。
关于java - 在这种情况下,ForkJoinPool 可以比 ExecutorService 更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15666978/