0

ArrayHoldertwoを実行する Java プログラムを実行する必要がありますThreadsArrayHolderがありますArrayThreadSevenそのすべての要素Arrayを 7ThreadOneと 1 で上書きします。実行後の結果は 7,1,7,1,7,1,7,1 などになります。より良い方法を提案していただければ幸いです。

ps: 両方のスレッドがすべてのインデックスに書き込む必要があります。

public class ArrayHolder {

    private int[] array = {1, 2, 3, 4, 5, 6, 4, 8, 9, 10};

    public void writeInt(int pos, int num) {
        array[pos] = num;
    }

    public static void main(String[] args) {
        ArrayHolder holder = new ArrayHolder();
        ThreadSeven seven = new ThreadSeven(holder, null);
        Runnable one = new ThreadOne(holder, seven);
        Thread thread1 = new Thread(seven);
        Thread thread2 = new Thread(one);
        seven.setThread(one);

        thread1.start();
        thread2.start();

        holder.printArray();
    }

    private void printArray() {
        for (int i = 0; i < 10; i++) {
            System.out.println(array[i]);
        }
    }

public class ThreadSeven implements Runnable {
    private ArrayHolder array;
    private Runnable t;
    private int flag=0;
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            array.writeInt(i, 7);

            flag=(flag+1)%2;
            if (flag==0){
                synchronized(t){
                    t.notify();
                }
            }else{
                synchronized(this){
                    try {
                        this.wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(ThreadSeven.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    }
    public ThreadSeven (ArrayHolder ar,Runnable t){
        array=ar;
        this.t=t;
    }
    public void setThread(Runnable t){
        this.t=t;
    }
}

public class ThreadOne implements Runnable {

    private ArrayHolder array;
    private Runnable t;
    private int flag = 0;

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            array.writeInt(i, 1);

            flag = (flag + 1) % 2;
            if (flag == 1) {
                synchronized (t) {
                    t.notify();
                }
            } else {
                synchronized (this) {
                    try {
                        this.wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(ThreadSeven.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    }

    public ThreadOne(ArrayHolder ar, Runnable t) {
        array = ar;
        this.t = t;
    }

    public void setThread(Runnable t) {
        this.t = t;
    }
}
4

2 に答える 2

0

あなたの解決策にはいくつかの問題があり、正しい結果を出力しないように私には見えます。

a)結果の配列を出力する前に、スレッドが終了するのを待たない

まだ存在しない場合に備えて、前にthread1.join()追加しthread2.join()ます。holder.printArray()

b)両方のスレッドは、を介してすぐに書き込みをarray.writeInt(0, /* 1 or 7 */);開始し、その後、互いに待機し始めます。最初のインデックスが正しいかどうかは運次第です。

c)this.wait();割り込みが他のスレッド以外の何かによって引き起こされた可能性があるため、条件をチェックするループなしで続行することは安全ではありません。ただの練習なので、ここでそれをしても大丈夫だと思います。

d)潜在的なデッドロックが発生しました。両方のスレッドがまだ最初のインデックスを書き込んでいると仮定しましょう。したがって、両方が同期ブロックに含まれていません。

他のスレッドに通知する必要があるスレッドは、次のインデックスを書き込み、それ自体の待機ブロックに入ります。しかし、2番目のスレッドはその時点で待機していなかったためnotify、最初のスレッドからは何もしませんでした。2番目のスレッドも待機ブロックに入ります。

これで、両方のスレッドが互いに待機し、何も起こりません。

その問題は非常に複雑なので、私はあなたのための素晴らしい簡単な解決策を持っていません。

1スレッドはインデックス0から書き込みを開始し、7スレッドがインデックス0と1を書き込むまで待機する必要があります。次に、1スレッドはインデックス1と2を書き込み、待機します。これが、両方のスレッドがすべてのインデックスに書き込まれ、結果が7-1-7-1 -...であることを確認できる唯一の方法です。内部でアクセスを同期するにArrayHolderは、両方を確認する必要があるため、非常に注意が必要です。スレッドは各インデックスに正しい順序で書き込まれています。

しかし、あなたの一般的な考えは大丈夫だと思います。あなたはそれが安全であることを確認する必要があります

于 2012-11-22T21:14:12.063 に答える