2016-12-20 53 views
2

我的任務是製作一個項目,它接受兩個矩陣的輸入維度,並讓用戶選擇他希望對這些矩陣執行的操作並輸出結果矩陣。增加的扭曲是它必須平行進行。對於每個元素/單元格,結果矩陣必須有一個線程。例如2x2和另一個2x2矩陣輸出4個元素。所以必須有4個線程對每個元素執行操作。這是我的矩陣代碼:在矩陣中實現線程陣

public class Matrix { 
     public int row,column; 
     private double [][] matrixElements; 

     public Matrix (int rows, int columns){ 
      this.row= rows; 
      this.column = columns; 
      matrixElements = new double[row][column]; 
      populatematrix(-100,100); 
     } 


     public Matrix(double[][] matrixArray){ 
      this.row = matrixArray.length; 
      this.column = (matrixArray[0]).length; 
      matrixElements = new double [row][column]; 
      for (int i=0; i<row;i++){ 
       for (int j=0; j<column;j++){ 
        matrixElements[i][j] = matrixArray[i][j]; 
       } 
      } 
     } 
     private void populatematrix(int min, int max){ 
      Random randnum = new Random(); 
      Random rand = new Random(); 

       for (int i=0; i<row; i++){ 
        for (int j= 0;i<row;i++){ 
         matrixElements[i][j] = rand.nextInt((max - min) + 1) + min; 
        } 
       } 
     } 
     public Matrix add(Matrix otherMatrix){ 
      double[][] resultMatrixArray = new double[this.row][this.column]; 
      for (int i=0; i<row; i++){ 
       for (int j=0; j<column; j++){ 
        resultMatrixArray[i][j] = this.matrixElements[i][j] + otherMatrix.matrixElements[i][j]; 

       } 

      } 
      return new Matrix(resultMatrixArray); 
     } 

     public Matrix subtract(Matrix otherMatrix){ 
      double[][] resultMatrixArray = new double[row][column]; 

      for (int i=0; i<row; i++){ 
       for (int j=0; j<column; j++){ 
        resultMatrixArray[i][j] = this.matrixElements[i][j] - otherMatrix.matrixElements[i][j]; 
       } 
      } 
      return new Matrix(resultMatrixArray); 

     } 




     public Matrix dotProduct(Matrix otherMatrix){ 

      double[][] resultMatrixArray = new double [row][column]; 

      double sum = 0; 

      if (this.column !=otherMatrix.row) 
       System.out.println("\n\n Matrices Multiplication is not possible...Invalid Dimensions...\n\n"); 
      else { 
       for (int c=0; c<this.row;c++){ 
        for (int d = 0; d<otherMatrix.column;d++){ 
         for (int k = 0; k<otherMatrix.row; k++){ 
          sum = sum+((this.matrixElements[c][k])*(otherMatrix.matrixElements[k][d])); 
         } 
         resultMatrixArray[c][d]=sum; 
         sum = 0; 
        } 
       } 
      } 
      return new Matrix(resultMatrixArray); 
     } 

     public String getPrintableMatrix(){ 
      String result =""; 

      for (double[] roww: matrixElements){ 
       for (double j:roww){ 
        result +=""+j + ""; 

       } 
       result +="\n"; 

      } 
      return result; 
     } 
} 

這裏是我用於查找任何操作的矩陣結果的方法的代碼。

public class MatrixOperations { 
    public static void main(String args[]){ 
     int row1,col1,row2,col2; 

     Scanner sc = new Scanner(System.in); 

     System.out.print("\n\n Input Matrix 1 dimensions (ROWS space COLUMNS):"); 
     row1= sc.nextInt(); 
     col1 = sc.nextInt(); 

     System.out.print("\n\n Input Matrix 2 dimensions (ROWS space COlUMNS):"); 
     row2= sc.nextInt(); 
     col2 = sc.nextInt(); 

     int operation; 

     System.out.print("\n\n Select the operation to executed: 1. Add 2. Subtract 3. Multiply \n > "); 
     operation = sc.nextInt(); 

     Matrix result; 
     Matrix m1 = new Matrix(row1, col1); 
     Matrix m2 = new Matrix(row2, col2); 

     Thread myThreads[] = new Thread[Matrix.row]; 
     switch(operation){ 
      case 1: 
       result = m1.add(m2); 
       System.out.println("\n\n First Matrix: \n " + m1.getPrintableMatrix()); 
       System.out.println("\n\n Second Matrix: \n " + m2.getPrintableMatrix()); 
       System.out.println("\n\n Resultant Matrix: \n " + result.getPrintableMatrix()); 

       break; 

      case 2: 
       result = m1.subtract(m2); 

       System.out.println("\n\n First Matrix: \n " + m1.getPrintableMatrix()); 
       System.out.println("\n\n Second Matrix: \n " + m2.getPrintableMatrix()); 
       System.out.println("\n\n Resultant Matrix: \n " + result.getPrintableMatrix()); 


       break; 

      case 3: 

       result = m1.dotProduct(m2); 

       System.out.println("\n\n First Matrix: \n " + m1.getPrintableMatrix()); 
       System.out.println("\n\n Second Matrix: \n " + m2.getPrintableMatrix()); 
       System.out.println("\n\n Resultant Matrix: \n " + result.getPrintableMatrix()); 

       break; 

      default: System.out.println("\nInvalid operation......\n");break; 
     } 

     System.out.print("\n\n"); 
    } 

}

這是我的用戶輸入的代碼。

我的問題是我將如何做到這一點。這是我的第一個並行項目,我知道我必須使用一組線程,但我不知道把它們放在哪裏,我嘗試了多種方式,似乎沒有人能夠幫助我。

我知道它需要一個線程數組,並且所需的數組數量是輸出矩陣中元素的數量,但我不知道在何處或如何實現該數組,因爲我以多種方式獲取錯誤我試過了。

回答

0

我會改變代碼結構ure,否則它可能太複雜,無法與Threads結合。上的矩陣元素

  • 移動原子操作(「+」,「 - 」,「*」)轉換成對應的功能接口
  • 創建一個單獨的功能,其處理矩陣,otherMatrix和所需的操作和隱藏所有的併發
  • 在上面的函數中,啓動具有所需線程數的ExecutorService(下例中爲4),並在提交所有任務時關閉它
  • 在應用操作之前識別結果矩陣行/列計數。 (*)注有在代碼中可能的錯誤,在dotProduct功能結果矩陣大小時並不需要new double [row][column]

請參見下面

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class Matrix { 

@FunctionalInterface 
interface MatrixOperation<Matrix, Integer> { 
    public void apply(Matrix m1, Matrix m2, Matrix m3, Integer i, Integer j); 
} 
private final static MatrixOperation<Matrix, Integer> addFunc = (m1, m2, m3, i, j) -> { 
    double value = m1.get(i, j) + m2.get(i, j); 
    m3.set(i, j, value); 
}; 
private final static MatrixOperation<Matrix, Integer> subtractFunc = (m1, m2, m3, i, j) -> { 
    double value = m1.get(i, j) + m2.get(i, j); 
    m3.set(i, j, value); 
}; 
private final static MatrixOperation<Matrix, Integer> productFunc = (m1, m2, m3, i, j) -> { 
    double value = 0; 
    for (int index = 0; index < m1.column; index++) { 
     value += m1.get(i, index) * m2.get(index, j); 
    } 
    m3.set(i, j, value); 
}; 
//Set number of threads 
private final static int threadCount = 4; 

public int row, column; 
private double[][] matrixElements; 


public Matrix(int rows, int columns) { 
    this.row = rows; 
    this.column = columns; 
    matrixElements = new double[row][column]; 
} 


public Matrix(double[][] matrixArray) { 
    this.row = matrixArray.length; 
    this.column = (matrixArray[0]).length; 
    matrixElements = new double[row][column]; 
    for (int i = 0; i < row; i++) { 
     for (int j = 0; j < column; j++) { 
      matrixElements[i][j] = matrixArray[i][j]; 
     } 
    } 
} 

public double get(int i, int j) { 
    return matrixElements[i][j]; 
} 

public void set(int i, int j, double value) { 
    matrixElements[i][j] = value; 
} 

private Matrix operation(Matrix m2, Matrix result, MatrixOperation<Matrix, Integer> operator) { 
    ExecutorService executor = Executors.newFixedThreadPool(threadCount); 
    for (int i = 0; i < result.row; i++) { 
     for (int j = 0; j < result.column; j++) { 
      final int i1 = i; 
      final int j1 = j; 
      executor.submit(new Runnable() { 
       @Override 
       public void run() { 
        operator.apply(Matrix.this, m2, result, i1, j1); 
       } 
      }); 

     } 
    } 
    try { 
     executor.shutdown(); 
     executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    return result; 
} 

public Matrix add(final Matrix m2) { 
    if (this.row != m2.row || this.column != m2.column) { 
     throw new IllegalArgumentException(); 
    } 
    return operation(m2, new Matrix(row, column), addFunc); 
} 

public Matrix subtract(Matrix m2) { 
    if (this.row != m2.row || this.column != m2.column) { 
     throw new IllegalArgumentException(); 
    } 
    return operation(m2, new Matrix(row, column), subtractFunc); 
} 


public Matrix dotProduct(Matrix m2) { 
    if (this.column != m2.row) { 
     throw new IllegalArgumentException(); 
    } 
    return operation(m2, new Matrix(row, m2.column), productFunc); 
} 

} 

一些提示代碼:

  • 在這種情況下,線程的數量無法成爲您計算機上的核心數量,這會使代碼變慢。
  • (!)ExecutorService.shutdown()強制執行程序在不接受新任務的情況下完成所有正在運行的任務。 ExecutorService.awaitTermination停止主線程直到所有任務完成。即,結果矩陣將 完全構建之前它是返回。
  • 只要不同的線程正在從矩陣和其他矩陣中讀取(在計算過程中不得更新),並寫入結果矩陣的不同位置(i,j),則代碼是線程安全的。
+0

嗨,謝謝你也幫我解決這個問題,我是新來的線程和並行編程,這幫助我非常感謝你 –

0

好吧不夠公平,好像你付出很大的努力,並願意學得更多,這裏是我的2%的:

你有一個農場。 139米長。你每年都會收集土豆(可以說)。您每小時花費1小時。所以,如果你工作每小時每年收穫大約需要天(139/12)。 然後你賺了一些錢,你僱用的傢伙。您將如何公平分擔土地:

139 is not dividable by 8 

所以,讓我們做一些清理和尋找差異:

139 % 8 = 3modulo

所以,現在你知道你有額外的米那你可以處理你自己。如果我們填補空白

(Total - Difference)/workers = meters per worker 

:和其他球員可以處理這樣

(139 - 3)/8 = 17 

因此,我們知道每個工人會爲米工作。等等,但是他們都不應該在第17米開始工作!我們要平分

所以我們會給每個工人的ID:

{0,1,2,3,4,5,6,7} 

然後我們會告訴工人從哪裏開始在哪裏使用他們的ID來結束:

start = id * step 
    end = start + step 

這將導致作爲開始,結束:

worker 0 will work: 0 until 17 (not including 17, 0 indexed ;)) 
    worker 1 will work: 17 until 34 
    worker 2 will work: 34 until 51 
    worker 3 will work: 51 until 68 
    worker 4 will work: 68 until 85 
    worker 5 will work: 85 until 102 
    worker 6 will work: 102 until 119 
    worker 7 will work: 119 until 136 

    and you = 136 until 139 (3 meter) 

因此,既然你有多維數組,你h大道內環路這樣的:

for (int i = 0; i < row; i++) { 
      for (int j = 0; j < column; j++) { 
       resultMatrixArray[i][j] = this.matrixElements[i][j] + otherMatrix.matrixElements[i][j]; 

      } 

     } 

你需要做的,你將創建threads並告訴他們每個人在哪裏開始和在哪裏什麼:

for (int i = start; i < end; i++) { 
      for (int j = 0; j < columns; j++) { 
       resultMatrixArray[i][j] = thisMatrix[i][j] + otherMatrix[i][j]; 

      } 

     } 

然後你可以做數學,做這樣的事情:

for(int i = 0; i < threadCount;i++){ 
      int start = i * step; 
      int end = start + step; 

    new Thread(new Add(....)).run(); 


} 
+0

非常感謝!我非常感謝您在幫助我的所有時間,這給了我一個全新的觀點,現在我終於知道該怎麼做了,謝謝! –