Java中的线程正在疯狂发展

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 {

我是一个新手,所以我们开始。。我有一个任务,我用两种方式乘以2个矩阵:并行和线程池。此外,我必须使用这个子任务,在这个子任务中,我计算结果矩阵中我需要使用的每个元素

无论我做什么,我的线程都是完全随机运行的,这意味着一些值会一次又一次地翻倍。我将附加一些输出,以便查看

这是我的乱码:

类别矩阵:


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);
        
                
        
        
        
            }
        }