有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程Java一次只运行一个线程,而它应该同时运行它们

下面的代码将矩阵列表相乘。有一个函数可以将列表拆分为两个列表,并在一个新线程中递归计算每个列表的输出矩阵。如果函数到达一个只包含一个矩阵的列表,它将返回该矩阵,否则它将获取上述两个列表的两个输出矩阵(假设第一个矩阵有k行),并创建k个线程,每个线程计算一行输出

import java.util.Scanner;

public class Q3_thread
{
    public static void main(String[] args)
    {
        // input
        // Note: input matrices are presumed correct and in order
        Scanner scanner = new Scanner(System.in);
        int count = scanner.nextInt();
        scanner.nextLine();
        Matrix[] matrices = new Matrix[count];
        for (int i = 0; i < matrices.length; i++)
        {
            String string = scanner.nextLine().trim();
            String[] dimensions = string.split("\\*");
            int m = Integer.valueOf(dimensions[0]), n = Integer.valueOf(dimensions[1]);
            matrices[i] = new Matrix(m, n);
            for (int j = 0; j < m; j++)
            {
                for (int k = 0; k < n; k++)
                {
                    matrices[i].a[j][k] = scanner.nextInt();
                }
                scanner.nextLine();
            }
        }
        scanner.close();
        // log
//      System.out.println('---');
//      for (int i = 0; i < matrices.length; i++)
//      {
//          System.out.print(matrices[i]);
//      }

        // output
        MatricesRunnable mainRunnable = new MatricesRunnable(matrices, 0, matrices.length);
        Thread mainThread = new Thread(mainRunnable);
        mainThread.start();
        try
        {
            mainThread.join();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.print(mainRunnable.output);
    }
}

class Matrix
{
    public int m, n;
    public int[][] a;

    public Matrix(int m, int n)
    {
        this.m = m;
        this.n = n;
        this.a = new int[m][n];
    }

    public static Matrix multiply(Matrix left, Matrix right)
    {
        Matrix output = new Matrix(left.m, right.n);
        RowRunnable[] rowRunnables = new RowRunnable[left.m];
        Thread[] threads = new Thread[left.m];
        for (int i = 0; i < threads.length; i++)
        {
            rowRunnables[i] = new RowRunnable(left, right, i);
            threads[i] = new Thread(rowRunnables[i]);
            threads[i].start();
        }
        for (int i = 0; i < threads.length; i++)
        {
            try
            {
                threads[i].join();
                output.a[i] = rowRunnables[i].output;
            }
            catch (InterruptedException e)
            {
                e.printStackTrace(System.err);
            }
        }
        return output;
    }

    @Override
    public String toString()
    {
        String output = "";
        for (int i = 0; i < this.m; i++)
        {
            for (int j = 0; j < this.n; j++)
            {
                output += this.a[i][j] + " ";
            }
            output += "\n";
        }
        return output;
    }
}

class MatricesRunnable implements Runnable
{
    public Matrix[] matrices;
    public int startIndex, endIndex;  // [,)
    public Matrix output;

    public MatricesRunnable(Matrix[] matrices, int startIndex, int endIndex)
    {
        this.matrices = matrices;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }

    @Override
    public void run()
    {
        if (this.endIndex - this.startIndex == 0)
        {
            output = null;
        }
        else if (this.endIndex - this.startIndex == 1)
        {
            output = matrices[this.startIndex];
        }
        else if (this.endIndex - this.startIndex == 2)
        {
            output = Matrix.multiply(matrices[this.startIndex], matrices[this.startIndex + 1]);
        }
        else
        {
            int halfIndex = (endIndex + startIndex) / 2;  // int division
            if ((this.endIndex - this.startIndex) % 2 == 1)  // so that the longer sublist is at left
            {
                halfIndex++;
            }
            MatricesRunnable leftMatrixRunnable = new MatricesRunnable(matrices, startIndex, halfIndex);
            Thread leftMatrixThread = new Thread(leftMatrixRunnable);
            leftMatrixThread.start();
            MatricesRunnable rightMatrixRunnable = new MatricesRunnable(matrices, halfIndex, endIndex);
            Thread rightMatrixThread = new Thread(rightMatrixRunnable);
            rightMatrixThread.start();
            try
            {
                leftMatrixThread.join();
                rightMatrixThread.join();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            output = Matrix.multiply(leftMatrixRunnable.output, rightMatrixRunnable.output);
        }
    }
}

class RowRunnable implements Runnable
{
    public Matrix left, right;
    public int index;  // which row
    public int[] output; // index-th row of output

    public RowRunnable(Matrix left, Matrix right, int index)
    {
        this.left = left;
        this.right = right;
        this.index = index;
        this.output = new int[this.right.n];
    }

    @Override
    public void run()
    {
        for (int i = 0; i < this.right.n; i++)
        {
            int sum = 0;
            for (int j = 0; j < this.left.n; j++)
            {
                sum += left.a[index][j] * right.a[j][i];
            }
            this.output[i] = sum; 
        }
    }
}

问题是,这段代码应该同时运行多个线程,但当我检查线程(使用htop命令)时,只有一个正在运行的线程,因此产生结果所需的时间与我根本不使用线程时所需的时间相同。为什么会这样

您可以使用以下代码生成测试用例:

#include <iostream>
#include <cstdlib>

using namespace std;

int main(int argc, char *argv[])
{
    srand(atoi(argv[1]));
    int n = atoi(argv[2]);
    int maxRC = atoi(argv[3]);
    int maxNum = atoi(argv[4]);
    cout << n << endl;
    int r = rand() % maxRC + 1;
    for(int i = 0; i < n; i++)
    {
    int c = rand() % maxRC + 1;
    cout << r << '*' << c << endl;
    for(int j = 0; j < r; j++)
    {
        for(int k = 0; k < c; k++)
        {
            cout << rand() % (maxNum + 1) << ' ';
        }
        cout << endl;
    }
    r = c;
    }
    return 0;
}

参数分别是:随机种子、矩阵数、行和列的最大长度、矩阵中的最大数


共 (1) 个答案

  1. # 1 楼答案

    你就是其他线程,它们的行为实际上就像一个连续的工作顺序

    在另一个线程上调用join方法会导致当前(调用)线程实际暂停并等待另一个线程完成其工作。事实上,这只会让你看到一个线程在一个时间点上工作,尽管在不同的时间点,这可能总是另一个线程


    编辑作为对评论的回应:

    有人可能认为调用thread.start()实际上启动了一个线程,但事实并非如此。这是对JVM的一个简单提示,现在可以启动一个新线程了

    创建所有这些线程、对它们调用start方法,然后加入它们之间的时间非常短,以至于您不会看到两个线程同时运行