java - 如何选择最佳线程数

标签 java multithreading

实际上,我编写了一个 Java 程序来计算斐波那契数列中的特定数字。

现在的问题是我使用的核心数作为所需的线程数。但我观察到,随着输入大小的增加,我通过增加线程数获得了更好的性能。

是否有关于如何将问题划分为多个线程的现有公式/理论?

源代码如下:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Fibonacci {
    private static long[] value;

    public static void main(String args[]) throws InterruptedException {
        int n;
        try {
            n = Integer.parseInt(args[0]);
        } catch (Exception e) {
            throw new RuntimeException(
                    "Please enter in the form java n number ");
        }
        value = new long[n + 1];


        long start = System.nanoTime();
        int nThreads = Runtime.getRuntime().availableProcessors();
        ExecutorService executorService = Executors
                .newFixedThreadPool(nThreads);
        int result;
        try {
            result = fibonacciSum(n, executorService);
        } catch (ExecutionException e) {
            throw new RuntimeException("Thread Interuppted ");
        }
        System.out.print(" MultiThreading = " + result);
        long end = System.nanoTime();
        System.out.println("\t time = " + (end - start) + "ns");
    }


    private static class FibonacciThread implements Runnable {
        int index;
        int result;
        ExecutorService executorService;

        public FibonacciThread(int index) {
            this.index = index;
        }

        public void run() {
            try {
                this.result = fibonacciSum(index, executorService);
            } catch (Exception e) {
                throw new RuntimeException("Thread interupted");
            }
        }
    }

    private static int fibonacciSum(int index, ExecutorService executorService)
            throws InterruptedException, ExecutionException {
        if (index <= 2) {
            return 1;
        } else {

            FibonacciThread fibonacciThread1 = new FibonacciThread(index - 2);
            fibonacciThread1.executorService = executorService;
            Future future = executorService.submit(fibonacciThread1);
            Object object = future.get();
            int resultPart2 = fibonacciSum(index - 1, executorService);
            int result = fibonacciThread1.result + resultPart2;
            // executorService.shutdown();
            return result;
        }
    }

}

最佳答案

如果您还没有意识到这一点,斐波那契数列不是并行化的理想选择。您将获得(越来越)更好的性能:

  • 通过使用单线程递归算法,
  • 通过使用带有内存的单线程递归算法,以及
  • 通过求解递归关系并实现所得公式。

基本问题是朴素的斐波那契计算需要指数级的计算步骤。您无法通过多线程对此(在性能方面)产生影响,因为您的处理器数量有限。

即使您确实拥有无限数量的处理器,线程设置/任务创建开销也会超过执行计算步骤的时间。

最后,使用执行程序服务和有界线程池执行斐波那契数列有一个特殊问题。如果线程池太小(或 N 太大),计算很容易卡住。例如,您编码的方式需要池中的 ~N 个线程来计算 fibonacci(N),即使它们中的大多数将被阻塞时间。 (理解这一点的最好方法是“手动执行”应用程序,注意每个时间点有多少线程在使用……以及它们在做什么。)


因此,您问题的简单答案是(对于这个特定的应用程序)池中至少需要 N 个线程才能完成 Fibonacci(N) 的计算>。 (这不是一般性答案。它是由您已实现的算法的细节强制要求的。)


还有很多关于使用线程计算斐波那契数的其他 SO 问题/答案。我建议您也阅读它们。

关于java - 如何选择最佳线程数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6560421/

相关文章:

python - 当一个线程失败时终止多线程代码的正确方法是什么?

c# - 使用 Interlocked 的线程安全 DateTime 更新。*

消费者-生产者。没有错误。有时工作。为什么?

c# - 从正在运行的线程 C# 更改窗体的属性

java - 为什么混合GC无法清除内存,而Full DC却可以?

java - Spring MVC url 模式 - 不断附加 Controller

java - 从Handler迁移到ScheduledExecutorService进行调度

Java:多线程

java - 向非循环图添加边

java - 单击管理按钮时显示自动售货机库存