Java一次运行一个线程就应该运行它们

时间:2014-12-03 13:35:30

标签: java multithreading

以下代码将矩阵列表相乘。有一个函数可以将列表分成两个列表,并以递归方式在新线程中计算每个列表的输出矩阵。如果函数到达只包含一个矩阵的列表,则返回矩阵,否则它将获取上述两个列表的两个输出矩阵(假设第一个矩阵有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 个答案:

答案 0 :(得分:0)

你是 joining 其他线程实际上就像一个连续的工作顺序。

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


编辑作为评论的anser:

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

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