Java ThreadPool限制了有史以来创建的最大线程

时间:2018-04-16 08:23:44

标签: java multithreading matrix-multiplication java-threads

我正在尝试编写一个Java多线程程序,在作为文件给出的2个矩阵上执行乘法,并使用有限的线程总数

例如,如果我在16处设置了多个线程,我希望我的线程池能够重用这16个线程,直到完成所有任务。

但是我最终会为更多的线程执行更长的时间,而且我很难理解为什么。

可运行:

class Task implements Runnable
{
    int _row = 0;
    int _col = 0;

    public Task(int row, int col)
    {
        _row = row;
        _col = col;
    }

    @Override
    public void run()
    {
        Application.multiply(_row, _col);
    }
}

应用

public class Application
{
    private static Scanner sc = new Scanner(System.in);

    private static int _A[][];
    private static int _B[][];
    private static int _C[][];

    public static void main(final String [] args) throws InterruptedException
    {                
        ExecutorService executor = Executors.newFixedThreadPool(16);
        ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

        _A = readMatrix();
        _B = readMatrix();
        _C = new int[_A.length][_B[0].length];

        long startTime = System.currentTimeMillis();
        for (int x = 0; x < _C.length; x++)
        {
            for (int y = 0; y < _C[0].length; y++)
            {
                executor.execute(new Task(x, y));
            }
        }
        long endTime = System.currentTimeMillis();

        executor.shutdown();
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);

        System.out.printf("Calculation Time: %d ms\n" , endTime - startTime);
   }

    public static void multMatrix(int row, int col)
    {
        int sum = 0;
        for (int i = 0; i < _B.length; i++)
        {
            sum += _A[row][i] * _B[i][col];
        }
        _C[row][col] = sum;
    }

    ...
}

矩阵计算和工作负载共享似乎是正确的,因此它可能来自ThreadPool的错误使用

3 个答案:

答案 0 :(得分:2)

上下文切换需要时间。 如果你有8个核心并且你正在执行8个线程,它们都可以同时工作,一旦完成它就会被重用。 另一方面,如果你有8个核心的16个线程,每个线程将争夺处理器时间,调度程序将切换这些线程,你的时间将增加到 - 执行时间+上下文切换。

线程越多,上下文切换越多,因此时间增加。

答案 1 :(得分:1)

这些线程已经被重用来执行任务,这是ThreadPoolExecutor的预期行为。

http://www.codejava.net/java-core/concurrency/java-concurrency-understanding-thread-pool-and-executors https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html

当您增加线程名称时,您的计算时间会更长,因为创建它们所需的时间大于并发性在执行相关的短任务时所提供的性能提升。

答案 2 :(得分:0)

使用提交而非执行

制作一份返回的Future列表,以便您可以等待它们。

List<Future<?>> futures = new ArrayList<>();

futures.add(executor.submit(new Task(x, y)));

然后等待这些期货完成。