-5

1..n の数字で埋められた n のサイズの配列があります。

m 個のスレッドを使用してこの配列を合計する必要があります。毎回 2 つの要素を取り、それらを合計して、その合計を配列に挿入します。

これが私がやろうとしたことです。

最初に同期部分

public class MultiThreadedSum {

    private ArrayBuffer ArrayBufferInst;
    private int Sum;
    private boolean Flag, StopFlag;

    public MultiThreadedSum(ArrayBuffer ArrayBufferInst) {
        this.ArrayBufferInst = ArrayBufferInst;
        Sum = 0;
        Flag = false;
        StopFlag = false;
    }

    public synchronized void Sum2Elements() {
        while(Flag){
            try {wait();}
            catch (InterruptedException e){}
        }
        Flag = true;
        if (StopFlag) {
            notifyAll();
            return;
        }
        System.out.println("Removing and adding 2 elements.");
        Sum = ArrayBufferInst.Sum2Elements();
        notifyAll();
    }

    public synchronized void InsertElement() {

        while(!Flag){
            try {wait();}
            catch (InterruptedException e){}
        }
        Flag = false;
        if (StopFlag) {
            notifyAll();
            return;
        }
        System.out.println("Inserting the sum.");
        ArrayBufferInst.InsertElement(Sum);
        if (ArrayBufferInst.RetunrSize() == 1) {
            StopFlag = true;
        }
        System.out.println(ArrayBufferInst);
        notifyAll();
    }

    public boolean ReturnStopFlag(){
        return StopFlag;
    }

    @Override
    public String toString(){
        return ArrayBufferInst.toString();
    }
}

m 個のスレッドを 2 つのグループに分割しました。半分は要約を行い、半分は待機と通知を使用して追加を行います。

public class Sum2ElementsThread implements Runnable{
    private MultiThreadedSum MultiThreadedSumInst;    
    public Sum2ElementsThread( MultiThreadedSum MultiThreadedSumInst){
        this.MultiThreadedSumInst = MultiThreadedSumInst;
    }

    @Override
    public void run() {
        while(!MultiThreadedSumInst.ReturnStopFlag())
            MultiThreadedSumInst.Sum2Elements();
    }
}

public class InsertThread implements Runnable{
    private MultiThreadedSum MultiThreadedSumInst;    
    public InsertThread( MultiThreadedSum MultiThreadedSumInst) {
        this.MultiThreadedSumInst = MultiThreadedSumInst;
    }

    @Override
    public void run() {
        while(!MultiThreadedSumInst.ReturnStopFlag())  {
            MultiThreadedSumInst.InsertElement();
        }
    }
}

ここにメインの一部があります:

ArrayBufferInst = new ArrayBuffer(n);

System.out.println("The Array");
System.out.println(ArrayBufferInst);

MultiThreadedSumInst = new MultiThreadedSum(ArrayBufferInst);

ExecutorService Threads = Executors.newCachedThreadPool();

for (i = 0; i < m/2; i++)
    Threads.execute( new Sum2ElementsThread(MultiThreadedSumInst) );
for (; i < m; i++)
    Threads.execute( new InsertThread(MultiThreadedSumInst) );
Threads.shutdown();
while(!MultiThreadedSumInst.ReturnStopFlag()){}
System.out.println("The sum of the array is " + MultiThreadedSumInst);

そしてバッファ

public class ArrayBuffer {
    private ArrayList<Integer> ArrayBufferInst;
    public ArrayBuffer(int SizeOfBuffer){
        int i;
        ArrayBufferInst = new ArrayList<>(SizeOfBuffer);
        for (i = 0; i < SizeOfBuffer; i++){
            ArrayBufferInst.add(i, i+1);
        }
    }

    public int Sum2Elements(){
        if (ArrayBufferInst.size() < 2){
            return -1;
        }
        return ArrayBufferInst.remove(0) + ArrayBufferInst.remove(0);
    }

    public void InsertElement(int Elem) {
        ArrayBufferInst.add(Elem);
    }
    public int RetunrSize(){
        return ArrayBufferInst.size();
    }
    @Override
    public String toString() {
        return ArrayBufferInst.toString();
    }
}

私の質問は、メインの終わりについてです。プログラムが停止することもあれば、停止しないこともあります。すべてのスレッドが実行メソッドを終了していることを確認したためです。

メッセージが表示される場合と表示されThe sum of the array isない場合があります。

4

2 に答える 2

1

あなたの問題はここにあります:

public synchronized void Sum2Elements() {
    while(Flag){
        try {wait();}
        catch (InterruptedException e){}
    }
    Flag = true;
    // rest of method omitted here
}

プログラムのこの部分が初めて実行されるときFlagは false であり、ループは無視されます。Flagこれがfalseに設定された唯一の場所であるため、このメソッドの後続の実行はすべてデッドロックになります。

ループには何もなく、中断後は次のサイクルに永遠breakに進むだけなので、中断しても機能しません。wait()

ああ、これを読んでください-Javaはc#ではありません

于 2013-05-22T07:16:16.797 に答える