2014-12-03 95 views
-1

以下代碼將矩陣列表相乘。有一個函數將列表分成兩個列表,並遞歸地在新線程中計算每個列表的輸出矩陣。如果函數到達僅包含一個矩陣的列表,則返回矩陣,否則它將採用上述兩個列表中的兩個輸出矩陣(假設第一個矩陣有k行),並創建k個線程,每個線程計算一行輸出。Java一次運行一個線程時,它應該一起運行它們

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

因爲你只有一個線程,它是mainThread,你必須創建多個線程。 – Lrrr 2014-12-03 13:38:06

+0

您是否確實看到多個現有線程活着並且只有一個正在運行,或者線程沒有產生? – chrylis 2014-12-03 13:40:17

+1

@Ali Amiri是的,但mainThread創建了兩個線程,每個線程創建兩個,...請仔細閱讀問題。 – Arianbakh 2014-12-03 13:41:04

回答

0

你是joining其他線程其實實際上表現得像一個連續的工作順序。

在另一個線程上調用join方法會導致當前(調用)線程實際暫停並等待另一個線程,直到它完成其工作。事實上,這可以讓你看到只有一個線程在一個單一的時間點工作,雖然有可能在不同時間看到它總是另一個線程。


的編輯作爲雁的評論:

有人可能會認爲調用thread.start()真正啓動一個線程,但這種情況並非如此。這是JVM的一個簡單提示,即現在可以啓動一個新線程。

創建所有這些線程之間,調用start方法,然後加入它們之間的時間太少,以至於看不到兩個線程同時運行。

+0

是的,但是在回去加入之前,他已經把所有的線程分開了。 – chrylis 2014-12-03 13:53:16

+0

這是真的,但我在創建兩個子線程後調用join(),所以最後一級(計算行)的所有線程都應該同時運行。 – Arianbakh 2014-12-03 13:54:33

+0

@chrylis但是,啓動這些線程然後加入它們之間的時間太短,它看起來像是一個動作。這太快了。 – Seelenvirtuose 2014-12-03 13:57:46

相關問題