【问题标题】:Fork and Join feature jdk7 number of threadsFork 和 Join 特性 jdk7 线程数
【发布时间】:2012-07-16 09:17:04
【问题描述】:

我一直在研究 JDK 7 的新特性,即 Fork 和 Join。在 Javadoc 中,它指出在 ForkJoinTask 中,不能仅在 ForkJoinPool 的上下文中进行分叉。但它没有提到fork() 方法调用是否创建了一个新线程。

ForkJoinPool 使用工作窃取算法来平衡线程之间的工作,但没有提到实际创建了多少线程。

我有一个任务,我应该以分而治之的方式分解,但我担心ForkJoinPool 创建了太多线程,并且会因为管理这些线程的开销而降低执行性能。

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 我认为 Fork-Join 的全部意义在于将开发人员从这种计算中解放出来,并在给定典型开销和 100% 并行执行的情况下自动确定理想的线程数。可能每个核心一个。但我不确定。
  • 我也是这么想的,但我不确定,也找不到任何体面的资源可以让我清除它,并且未经确认我无法使用它。
  • 额外线程的成本非常接近于零,不值得担心。它比创建太少线程的惩罚要少很多数量级,以至于创建一些额外的线程很常见。你不应该假设开发你平台的人是白痴,你应该使用他们给你的工具来达到他们想要的目的。如果他们是白痴,那你就完蛋了。
  • 你有很多事情要担心。 [什么决定了 Java ForkJoinPool 创建的线程数?][1] [1]:stackoverflow.com/questions/10797568/…

标签: java multithreading concurrency java-7


【解决方案1】:

Fork 不会(必然)创建新线程。在我的基准测试中,每个可用核心仅创建 1 个线程 + 1 个额外线程。附加基准;比如说,从 main() 调用 Factorizer.factorize(71236789143834319L)

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class Factorizer extends RecursiveTask<Long> {

static ForkJoinPool fjPool = new ForkJoinPool();
static final int sequentialThreshold = 10000;

private long number, low, high;

Factorizer(long number, long low, long high) {
    this.number = number; this.low = low; this.high = high;
}

private long factorize() {
    if ((number % 2) == 0) {
        return 2;
    }
    // ensures i is odd (we already know number is not even)
    long i = ((low % 2) == 0) ? low + 1: low;
    for (/**/; i < high; i+=2) {
        if ((number % i) == 0) {
            return i;
        }
    }
    return number;
}

@Override
protected Long compute() {

    // ugly debug statement counts active threads
    System.err.println(Thread.enumerate(
            new Thread[Thread.activeCount()*2]));

    if (high - low <= sequentialThreshold) {
        return factorize();
    } else {
        long mid = low + (high - low) / 2;
        Factorizer left = new Factorizer(number, low, mid);
        Factorizer right = new Factorizer(number, mid, high);
        left.fork();
        return Math.min(right.compute(), left.join());
    }
}

static long factorize(long num) {
    return fjPool.invoke(new Factorizer(num, 2, (long)Math.sqrt(num+1)));
}
}

注意 - 这只是一个测试。请勿使用此代码来认真考虑任何重要因素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-08
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 2021-06-12
    • 2011-02-02
    • 1970-01-01
    相关资源
    最近更新 更多