package thread;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class Exercise30_16 {
public static void main(String[] args) {
final int SIZE = 2000;
double[][] a = new double[SIZE][SIZE]; //待运算数组
double[][] b = new double[SIZE][SIZE];
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
a[i][j] = Math.random() * 20; //初始化赋值
b[i][j] = Math.random() * 20;
}
}
//测试顺序矩阵加法
long startTime = System.currentTimeMillis();
double[][] result = addMatrix(a, b);
long endTime = System.currentTimeMillis();
System.out.println("The sequential time is " + (endTime - startTime) + " milliseconds\n");
//测试并行矩阵加法
startTime = System.currentTimeMillis();
result = parallelAddMatrix(a, b);
endTime = System.currentTimeMillis();
System.out.println("\n\nThe number of processors is " + Runtime.getRuntime().availableProcessors());
System.out.println("The time is " + (endTime - startTime) + " milliseconds");
}
/** 打印矩阵运算 */
public static void printMatrix(double[][] a, double[][] b, double[][] result, char op) {
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[0].length; j++)
System.out.printf("%-8.2f", a[i][j]);
if (i % 2 == 0)
System.out.print("\t\t\t");
else
System.out.print("\t" + op + "\t\t");
for (int j = 0; j < result[0].length; j++)
System.out.printf("%-8.2f", b[i][j]);
if (i % 2 == 0)
System.out.print("\t\t\t");
else
System.out.print("\t=\t\t");
for (int j = 0; j < result[0].length; j++)
System.out.printf("%-8.2f", result[i][j]);
System.out.println();
}
}
/** 顺序矩阵加法 */
public static double[][] addMatrix(double[][] a, double[][] b) {
if (a.length != b.length || a[0].length != b[0].length) //矩阵行不相等或列不相等时,抛出异常
throw new IllegalArgumentException("Illegal array length");
double[][] result = new double[a.length][a[0].length];
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[i].length; j++)
result[i][j] = a[i][j] + b[i][j]; //执行加法运算
}
return result;
}
/** 并行矩阵加法 */
public static double[][] parallelAddMatrix(double[][] a, double[][] b) {
if (a.length != b.length || a[0].length != b[0].length)
throw new IllegalArgumentException("Illegal array length");
double[][] result = new double[a.length][a[0].length];
RecursiveAction mainTask = new AddMatrixTask(a, b, result, 0, a[0].length);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(mainTask);
return result;
}
/** 内部类-矩阵加法任务类 */
private static class AddMatrixTask extends RecursiveAction {
private static final int THRESHOLD = 100; //最低门槛
private double[][] a, b, result; //待运算数组、结果数组
private int low, high; //起始、终止下标
public AddMatrixTask(double[][] a, double[][] b, double[][] result, int low, int high) {
this.a = a;
this.b = b;
this.result = result;
this.low = low;
this.high = high;
}
@Override
protected void compute() {
if (high - low < THRESHOLD) { //长度小于门槛时执行顺序矩阵加法
int highIndex = result.length == result[0].length ? high : high << 1; //n阶矩阵还是m*n矩阵
for (int i = low; i < highIndex; i++)
for (int j = low; j < high; j++)
result[i][j] = a[i][j] + b[i][j];
} else { //执行并行矩阵加法
int mid = (low + high) / 2;
invokeAll(new AddMatrixTask(a, b, result, low, mid),
new AddMatrixTask(a, b, result, mid, high));
}
}
}
}