以下代码将矩阵列表相乘。有一个函数可以将列表分成两个列表,并以递归方式在新线程中计算每个列表的输出矩阵。如果函数到达只包含一个矩阵的列表,则返回矩阵,否则它将获取上述两个列表的两个输出矩阵(假设第一个矩阵有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;
}
参数分别为:随机种子,矩阵数,行和列的最大长度,矩阵中数字的最大值
答案 0 :(得分:0)
你是 joining 其他线程实际上就像一个连续的工作顺序。
在另一个线程上调用join
方法会导致当前(调用)线程实际暂停并等待另一个线程,直到它完成其工作。实际上,只允许您在一个时间点看到一个线程正在工作,尽管在不同时间查看这个线程时可能总是另一个线程。
编辑作为评论的anser:
有人可能认为调用thread.start()
实际上启动了一个线程,但实际情况并非如此。这是JVM的一个简单提示,现在可以启动一个新线程。
创建所有这些线程,在它们上面调用start
方法然后加入它们之间的时间非常短,以至于你不会看到两个线程同时运行。