0

複数のスレッドと同期を正常に使用する方法を探していました。wait() と notify() を使用してみましたが、スレッドはまだ同期しません。私はより大きなプロジェクトを持っていますが、一言で言えば、セッターメソッド(この場合はスレッド1)でスレッドを所定の回数実行する必要があり、各「セット」の後にゲッターメソッド(スレッド2)でスレッドが必要です実行してオブジェクトを取得します。他の多くの例を見てきましたが、解決できないようです。なぜこれが機能しないのかについての助けや説明をいただければ幸いです。

これは、thread1 が最初に実行されるときに機能する場合もありますが、thread2 が最初に実行される場合もあるため、同期は機能しません。

ありがとう。

import java.util.ArrayList;

public class ThreadTest{

    private ArrayList<Object> myList;

    public ThreadTest(){

        myList = new ArrayList<Object>();

        Thread thread1 = new Thread(){
            public void run(){
                for(int i = 0; i < 10; i++){
                    addToList("" + i);
                }
            }
        };

        Thread thread2 = new Thread(){
            public void run(){
                for(int i = 0; i < 10; i++){
                    System.out.print(myList.get(i) + " ");
                }
            }
        };

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

    public synchronized void addToList(String a){
        myList.add(a);
        notify();
    }

    public synchronized ArrayList<Object> getList(){
        try{
            wait();
        }
        catch (InterruptedException e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return myList;
    }

    public static void main(String[] args){
        new ThreadTest();
    }
}
4

3 に答える 3

2

aBlockingQueueを使用して自動的に同期を行い、 an を使用ExecutorServiceしてすべてのThreadsを処理します

public void doStuff() {
    final Object finishSupplying = new Object();
    final BlockingQueue<Object> myList = new LinkedBlockingQueue<Object>();
    final Runnable supplier = new Runnable() {
        public void run() {
            for (int i = 0; i < 10; i++) {
                myList.add(i);
            }
        }
    };

    final Runnable consumer = new Runnable() {
        public void run() {
            while (true) {
                try {
                    final Object thing = myList.take();
                    if(thing == finishSupplying) break;
                    System.out.print(thing + " ");
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    };

    final ExecutorService exectutorService = Executors.newFixedThreadPool(2);
    final Future<?> supplierHandle = exectutorService.submit(supplier);
    final Future<?> consumerHandle = exectutorService.submit(consumer);
    try {
        supplierHandle.get();
    } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
    } catch (ExecutionException ex) {
        //PROBLEMS, handle
    }
    myList.add(finishSupplying);
    try {
        consumerHandle.get();
    } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
    } catch (ExecutionException ex) {
        //PROBLEMS, handle
    }
}

shutdown()完了したら必ず確認してくださいExecutorService。そうしないと、プログラムが終了しません。

于 2013-03-09T20:42:54.603 に答える
1

通知するときは、待機時にループでチェックする必要がある状態を (あなたが持っているように) 更新する必要があります。これは次のように必要です。

  • 待機が開始され、シグナルが失われる前の通知トリガー
  • 待機は誤ってウェイクアップする可能性があります。

注:待機するものを何も呼び出していないため、消費スレッドは待機しません。

これを修正する方法はいくつかありますが、私見では、このパターンをサポートするように設計された BlockingQueue を使用するのが最善の解決策です。

于 2013-03-09T20:23:33.167 に答える
0

getter と setter を使用してリスト全体にアクセスするのではなく、リストから要素をプッシュおよびプルする場合にのみ使用してください。言われているようにBlockingQueue、同期リストの実装です。

つまり、これを自分で実装する場合は、getList をremove(0)、ArrayList の最初の要素のみを返すリストで同期されたものに置き換えます。

于 2013-03-09T20:42:18.420 に答える