1

まず第一に、ここにコードがあります。貼り付けをコピーするだけです

import java.util.ArrayList;

public class RepetionCounter implements Runnable{
private int x;
private int y;
private int[][] matrix;
private int xCounter;
private int yCounter;
private ArrayList<Thread> threadArray;
private int rowIndex;
private boolean[] countCompleted; 

public RepetionCounter(int x, int y, int [][]matrix)
{
    this.x = x;
    this.y = y;
    this.matrix = matrix;
    this.threadArray = new ArrayList<Thread>(matrix.length);
    this.rowIndex = 0;
    for(int i = 0; i < matrix.length; i++){
        threadArray.add(new Thread(this));
    }
    countCompleted = new boolean[matrix.length];
}

public void start(){
    for (int i = 0; i < threadArray.size(); i++){
        threadArray.get(i).start();
        this.rowIndex++;
    }
}

public void count(int rowIndex)
{
    for(int i = 0; i < matrix[rowIndex].length; i++){
        if (matrix[rowIndex][i] == x){
            this.xCounter++;
        } else if (matrix[rowIndex][i] == y){
            this.yCounter++;
        }
    }
}

@Override
public void run() {
    count(this.rowIndex);
    countCompleted[this.rowIndex] = true;
}

public int getxCounter() {
    return xCounter;
}

public void setxCounter(int xCounter) {
    this.xCounter = xCounter;
}

public int getyCounter() {
    return yCounter;
}

public void setyCounter(int yCounter) {
    this.yCounter = yCounter;
}

public boolean[] getCountCompleted() {
    return countCompleted;
}

public void setCountCompleted(boolean[] countCompleted) {
    this.countCompleted = countCompleted;
}

public static void main(String args[]){
    int[][] matrix = {{0,2,1}, {2,3,4}, {3,2,0}};
    RepetionCounter rc = new RepetionCounter(0, 2, matrix);
    rc.start();
    boolean ready = false;
    while(!ready){
        for(int i = 0; i < matrix.length; i++){
            if (rc.getCountCompleted()[i]){
                ready = true;
            } else {
                ready = false;
            }
        }
    }
    if (rc.getxCounter() > rc.getyCounter()){
        System.out.println("Thre are more x than y");
    } else {System.out.println("There are:"+rc.getxCounter()+" x and:"+rc.getyCounter()+" y");

    }
}

}

このコードで実行したいこと: オブジェクトに行列と 2 つの数字を指定し、これら 2 つの数字が行列内で何回出現するかを知りたいと考えています。行列の行数と同じ数のスレッドを作成するため (その ArrayList が存在する理由)、このオブジェクトには k 個のスレッドがあり (k が行数であると仮定)、それぞれが 2 つのスレッドの出現をカウントします。数字。問題は、最初に実行するとすべてが機能しますが、別のときに実行しようとすると、 IndexOutOfBoundException が発生するか、発生回数が悪い場合、奇妙なことに、エラーが発生して変更するとコード、その後は一度だけ再び機能します。なぜこれが起こっているのか説明してもらえますか?

4

2 に答える 2

2

各スレッドに独自の Runnable を与える必要があります。それらすべてが同じ Runnable を共有すると、悲惨な競合状態が発生します。各スレッドが実行する必要があるロジックを Runnable に分離します。次に、スレッドを開始するコードの部分を Runnable の外の場所に移動します。

ところで、java.util.concurrent パッケージのエグゼキューターを調べてください。このようなものに生のスレッドを使用する必要はありません。また、エグゼキューターを使用すると、タスクに含まれるものを他のものから分離することについて、より良いアイデアが得られる場合があります。

于 2012-10-06T15:29:58.680 に答える
2

RepetitionCounter各スレッドの同じインスタンスを使用しています:

for(int i = 0; i < matrix.length; i++){
    threadArray.add(new Thread(this));
}

したがって、それらはすべて同じものを共有しrowIndexます。コードはそのままではかなり混乱するので、Runnable個々の行 ID を持つ別のクラスにスレッドのロジックをカプセル化することをお勧めします。

class ThreadTask implements Runnable {
    private int rowId;
    private int[][] matrix;

    public ThreadTask(int[][] matrix, int rowId) {
        this.matrix = matrix; // only a reference is passed here so no worries
        this.rowId = rowId;
    }

    public void run() {
       // search on my row
    }
}

それから:

for(int i = 0; i < matrix.length; i++) {
     threadArray.add(new Thread(new ThreadTask(matrix, i)));
}
于 2012-10-06T15:30:18.210 に答える