Java中的线程正在疯狂发展
我是一个新手,所以我们开始。。我有一个任务,我用两种方式乘以2个矩阵:并行和线程池。此外,我必须使用这个子任务,在这个子任务中,我计算结果矩阵中我需要使用的每个元素 无论我做什么,我的线程都是完全随机运行的,这意味着一些值会一次又一次地翻倍。我将附加一些输出,以便查看 这是我的乱码: 类别矩阵:Java中的线程正在疯狂发展,java,multithreading,concurrency,threadpool,Java,Multithreading,Concurrency,Threadpool,我是一个新手,所以我们开始。。我有一个任务,我用两种方式乘以2个矩阵:并行和线程池。此外,我必须使用这个子任务,在这个子任务中,我计算结果矩阵中我需要使用的每个元素 无论我做什么,我的线程都是完全随机运行的,这意味着一些值会一次又一次地翻倍。我将附加一些输出,以便查看 这是我的乱码: 类别矩阵: import java.util.ArrayList; import java.util.List; import java.util.Random; public class Matrix {
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Matrix {
private List<List<Integer>> matrix;
Random random = new Random();
private int rows;
private int cols;
public Matrix(int row, int col)
{
this.rows = row;
this.cols = col;
makeRandomMatrix(rows, cols);
}
public List<Integer> getRow(int index)
{
return this.matrix.get(index);
}
public List<Integer> getCol(int index)
{
List<Integer> col = new ArrayList<>();
for (List<Integer> row: this.matrix){
col.add(row.get(index));
}
return col;
}
public void setRow(int rowNo, List<Integer> row) throws Exception {
if (row.size() != this.cols){
throw new Exception("Cannot add row of length " + String.valueOf(row.size()) + " to a " + "(" + String.valueOf(this.rows) + ", " + String.valueOf(this.cols) + ") matrix");
}
this.matrix.set(rowNo, row);
}
public void setCol(int colNo, List<Integer> col) throws Exception {
if (col.size() != this.rows){
throw new Exception("Cannot add col of length " + String.valueOf(col.size()) + " to a " + "(" + String.valueOf(this.rows) + ", " + String.valueOf(this.cols) + ") matrix");
}
for (int i = 0; i < col.size(); i++){
this.matrix.get(i).set(colNo, col.get(i));
}
}
public int get(int row, int col){
return this.matrix.get(row).get(col);
}
public void set(int row, int col, int value){
this.matrix.get(row).set(col, value);
}
public int getRowsNumber() {
return rows;
}
public int getColsNumber() {
return cols;
}
public int index(int row, int col){
return row * this.cols + col;
}
@Override
public String toString() {
StringBuilder ss = new StringBuilder();
for (int i = 0; i < this.rows; i++){
ss.append(this.matrix.get(i).toString()).append("\n");
}
return ss.toString();
}
public void makeRandomMatrix(int rows, int cols)
{
this.matrix = new ArrayList<>(rows);
for (int i = 0; i < this.rows; i++)
{
this.matrix.add(new ArrayList<>(cols));
for (int j = 0; j < this.cols; j++)
{
this.matrix.get(i).add(random.nextInt(10));
}
}
}
public void makeEmptyMatrix(int rows, int cols)
{
this.matrix = new ArrayList<>(rows);
for (int i = 0; i < this.rows; i++)
{
this.matrix.add(new ArrayList<>(cols));
for (int j = 0; j < this.cols; j++)
{
this.matrix.get(i).add(0);
}
}
}
}
这就是我到目前为止所掌握的我不明白如何同步代码。通常需要同步数据结构以防止并发操作,以便多个线程可以安全地操作它们。如果一个线程处于同步方法中,则所有其他线程都无法进入此块。 您可能希望将问题分为多个部分,例如矩阵的一部分。考虑函数的输入和输出。 例如,将大矩阵拆分为多个小矩阵,然后构建一个要执行的任务队列。每个任务都有输入(m1,m2)和输出(r)。处理完所有任务后,您可以组合结果矩阵。 如果使用Collections.synchronizedCollection(),则启动的每个线程都可以从列表中提取下一个任务,对其进行处理并将结果放入结果列表,直到任务列表为空。在任务列表为空且您拥有所有结果后,您可以组合结果。
这描述了这个想法。尝试用一个线程处理列表,然后启动多个线程。如果您已经启动并运行了这个程序,您可能需要进行优化。我不明白您是如何同步代码的。通常需要同步数据结构以防止并发操作,以便多个线程可以安全地操作它们。如果一个线程处于同步方法中,则所有其他线程都无法进入此块。 您可能希望将问题分为多个部分,例如矩阵的一部分。考虑函数的输入和输出。 例如,将大矩阵拆分为多个小矩阵,然后构建一个要执行的任务队列。每个任务都有输入(m1,m2)和输出(r)。处理完所有任务后,您可以组合结果矩阵。 如果使用Collections.synchronizedCollection(),则启动的每个线程都可以从列表中提取下一个任务,对其进行处理并将结果放入结果列表,直到任务列表为空。在任务列表为空且您拥有所有结果后,您可以组合结果。
这描述了这个想法。尝试用一个线程处理列表,然后启动多个线程。如果您已经启动并运行了这个程序,您可能需要对其进行优化。您的代码有很多地方出错。这里最大的问题是,您的线程正在修改共享结果
矩阵
,而没有任何数据同步。每当两个线程修改同一个对象时,您都需要弄清楚如何保护它免受数据和逻辑争用条件的影响。线程之所以能获得速度,是因为它们在运行它们的CPU上利用了内存缓存。每个线程都会在自己的CPU缓存中更新其结果的副本,而对缓存副本的更改如何使其进入主内存并不由程序定义。我打赌每次运行程序都会看到不同的结果
您当然可以将矩阵
中的每个方法标记为已同步
,但这会导致大量数据争用,并会降低程序的速度。如果线程处理矩阵的不同部分,我建议每个线程修改自己的矩阵
,然后在线程完成后合并这些矩阵
此外:
- 您的
类应该实现multilyworkerThread
,但不能扩展Runnable
线程。线程池为您创建线程。应该将其重命名为
或其他名称多工任务
方法上的multiplyParallel(…)
关键字不起任何作用,因为没有多个线程同时调用该方法。如果有问题,仅仅因为您使用了该关键字并不能保护在方法内部创建的共享synchronized
结果
矩阵
- 当(!executorService.isTerminated())非常昂贵时,您的
正在旋转。在循环中放入
,或者最好使用线程.sleep(…)
ExecutorService.waittermination(…)
- 如果您的矩阵使用数组而不是列表,那么它的效率会更高
- 您的代码有很多地方出错。这里最大的问题是,您的线程正在修改共享结果
矩阵
,而没有任何数据同步。每当两个线程修改同一个对象时,您都需要弄清楚如何保护它免受数据和逻辑争用条件的影响。线程之所以能获得速度,是因为它们在运行它们的CPU上利用了内存缓存。每个线程都会在自己的CPU缓存中更新其结果的副本,而对缓存副本的更改如何使其进入主内存并不由程序定义。我打赌每次运行程序都会看到不同的结果
您当然可以将矩阵
中的每个方法标记为已同步
,但这会导致大量数据争用,并会降低程序的速度。如果线程处理矩阵的不同部分,我建议每个线程修改自己的矩阵
,然后在线程完成后合并这些矩阵
此外:
- 您的
类应该实现multilyworkerThread
,但不能扩展Runnable
线程。线程池为您创建线程。应该将其重命名为
或其他名称多工任务
上的
关键字synchronized
import com.sun.source.tree.MemberReferenceTree; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; public class MatrixOperations { private Matrix a; private Matrix b; private ReentrantLock lock; public MatrixOperations(Matrix aa, Matrix bb) { this.a = aa; this.b = bb; this.lock = new ReentrantLock(); } public Matrix getA() { return a; } public Matrix getB() { return b; } @Override public String toString() { return "MatrixOperations{" + "a=" + a + ", b=" + b + '}'; } public void multiply(Matrix a, Matrix b) { assert a.getRowsNumber() == b.getColsNumber(); Matrix result = new Matrix(a.getRowsNumber(), b.getColsNumber()); for (int i = 0; i < a.getRowsNumber(); i++) { for (int j = 0; j < b.getColsNumber(); j++) { result.set(i, j, 0); for (int k = 0; k < result.getRowsNumber(); k++) { result.set(i, j, result.get(i, j) + a.get(i, k) * b.get(k, j)); } } } System.out.print(result); } public void subTaskMultiply(Matrix a, Matrix b, Matrix result, int rowIndexA, int rowIndexB) { for(int i=0;i<a.getColsNumber();i++) { result.set(rowIndexA, rowIndexB, result.get(rowIndexA, rowIndexB) + a.get(rowIndexA, i) * b.get(i, rowIndexB)); } System.out.println(result); } public synchronized void multiplyParallel(Matrix a, Matrix b, int threadCount) throws InterruptedException { Matrix result = new Matrix(a.getRowsNumber(), b.getColsNumber()); result.makeEmptyMatrix(a.getRowsNumber(), b.getColsNumber()); List<Thread> threads = new ArrayList<>(); for(int i=0;i<threadCount;i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+" Start."); result.makeEmptyMatrix(a.getRowsNumber(), b.getColsNumber()); for(int i=0;i<a.getRowsNumber();i++) { for(int j=0;j<b.getColsNumber();j++) { subTaskMultiply(a,b,result, i,j); } } System.out.println(Thread.currentThread().getName()+" End."); } }); thread.start(); threads.add(thread); } for(Thread threadd : threads) { try{ threadd.join(); } catch(Exception e) { e.printStackTrace(); } } threads.clear(); } public void multiplyThreadPool(Matrix a, Matrix b) { Matrix result = new Matrix(a.getRowsNumber(), b.getColsNumber()); result.makeEmptyMatrix(a.getRowsNumber(), b.getColsNumber()); ExecutorService executorService = Executors.newFixedThreadPool(10); for(int i=0;i<10;i++) { Runnable worker = new MultiplyWorkerThread(a,b, result, a.getRowsNumber(), b.getColsNumber(), this); executorService.execute(worker); } executorService.shutdown(); while(!executorService.isTerminated()) { } System.out.println("Finished with all threads"); } }
public class MultiplyWorkerThread extends Thread implements Runnable { private Matrix a; private Matrix b; private Matrix result; private int indexA; private int indexB; private MatrixOperations op; public MultiplyWorkerThread(Matrix aa, Matrix bb, Matrix result, int indexa, int indexb, MatrixOperations opp) { this.a = aa; this.b = bb; this.result = result; this.indexA = indexa; this.indexB = indexb; this.op = opp; } @Override public void run() { System.out.println(Thread.currentThread().getName()+" Start."); result.makeEmptyMatrix(a.getRowsNumber(), b.getColsNumber()); for(int i=0;i<indexA;i++) { for(int j=0;j<indexB;j++) { op.subTaskMultiply(a,b,result, i,j); } } System.out.println(Thread.currentThread().getName()+" End."); } @Override public String toString() { return "MultiplyWorkerThread{" + "a=" + a + ", b=" + b + ", op=" + op + '}'; } }
import java.sql.SQLSyntaxErrorException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { public static void main(String[] args) throws InterruptedException { Matrix a = new Matrix(2,2); a.makeRandomMatrix(2,2); Matrix b = new Matrix(2,2); b.makeRandomMatrix(2,2); MatrixOperations op = new MatrixOperations(a,b); System.out.println(a); System.out.println(b); System.out.println("SIMPLE MULTIPLY"); op.multiply(a,b); System.out.println("THREAD POOL MULTIPLY: "); op.multiplyParallel(a,b,12); } }