2014-12-03 1 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 명령을 사용)이며 스레드를 전혀 사용하지 않을 때와 마찬가지로 결과를 생성합니다. 왜 그런 경우입니까?

는 당신을 testcases를 생성하기 위해 다음 코드를 사용할 수 있습니다

#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

+0

실제로 여러 개의 기존 스레드가 실행 중이며 하나만 실행 중이거나 스레드가 전혀 생성되지 않았습니까? – chrylis

+1

@Ali Amiri 네,하지만 mainThread는 두 개의 스레드를 만들고 두 스레드는 각각 두 개 더 만듭니다. 더 자세히 질문을 읽어보십시오. – Arianbakh

답변

0

당신은 joining 다른 스레드는 사실 순차적 인 작업 순서처럼 동작합니다.

다른 스레드에서 join 메서드를 호출하면 현재 (호출중인) 스레드가 실제로 일시 중지되고 작업을 완료 할 때까지 다른 스레드를 기다립니다. 사실, 한 번에 하나의 스레드 만 작업 할 수 있습니다.하지만 다른 시간에 보면 항상 다른 스레드가 될 가능성이 있습니다.


의견에 대한 답변와 같은 편집 :

하나는 thread.start()를 호출하면 실제로 스레드를 시작 생각할 수도 있지만,이 경우되지 않습니다. 새로운 스레드가 이제 시작될 수 있다는 것은 JVM에 대한 간단한 힌트입니다.

모든 스레드를 생성하고 그 스레드에서 start 메서드를 호출 한 후 결합하는 시간이 너무 짧아서 동시에 실행되는 두 개의 스레드가 표시되지 않습니다.

+0

그래,하지만 그는 다시 참여하기 전에 모든 스레드를 돌리고있다. – chrylis

+0

사실이지만, 두 하위 스레드를 모두 생성 한 후에 join()을 호출하므로 마지막 수준 (행 계산)의 모든 스레드가 동시에 실행되어야합니다. – Arianbakh

+0

@chrylis하지만 그 스레드를 시작한 후 결합하는 시간은 너무 짧아서 단일 작업처럼 보일 것입니다. 그것은 너무 빠릅니다. – Seelenvirtuose

관련 문제