java - 在这种情况下,ForkJoinPool 可以比 ExecutorService 更快吗?

标签 java multithreading java-7 fork-join

只要我在池中为 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;
    }
}

最佳答案

您的个人任务可以使两者 ForkJoinPoolExecutorService 运行得比现在更快,而且两者都不是一个应该比另一个有很大的优势。

原因是,如果单个计算任务是 Thread.sleep(1000) ,则该任务不需要 CPU 资源。您可以增加线程数以匹配您的作业大小 (80),并在略多于 1 秒的运行时间内完成 80 秒的“工作”,因为线程实际上不会竞争任何类型的资源。

至于 ForkJoinPoolExecutorService 之间的比较,差异与您的测试用例无关,因为您的工作不会产生任何应该的结果进一步计算的输入( MapReduce 中的“减少”步骤)。所以对你来说,它们都只是具有不同 API 的线程池。

关于java - 在这种情况下,ForkJoinPool 可以比 ExecutorService 更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15666978/

相关文章:

java-7 - 使用ASM api构造FrameNode

java - 如何使用JPanel鼠标监听器

java - JTextField 正在更新字符串数据和垃圾数据

java - 如果数组中有零,如何将数组中的元素向左移动 1?

java - Java 中的 "this"引用是否为空

ubuntu - 无法在 ubuntu 中将 java 版本从 1.8 降级到 1.7

java - Java7 垃圾优先收集器如何工作?

android - 线程正在卡住 Android 应用程序上的 Activity

java - 如果线程本身不请求锁,它可以更改 java 锁定的对象数据吗?

java - Android SQL 数据库打开和关闭 - 竞争条件