2

キュー内の操作を処理するスレッドがあります。基本的に、永遠にループします。キューに操作がある場合は、操作をデキューして実行します。操作がない場合は、操作があると言われるまで待ちます。

疑似コード (ここではクリティカル セクションを無視します):

public class OperationHandler extends Thread {
    private Deque<Operation> queue = new LinkedList<>();
    public void run() {
        while (true) {
            if (queue isn't empty) {
                 dequeue the operation and execute it
            }
            else {
                wait;
            }
        }
    }

    public void operationRequired() {
        add operation to queue
        notify yourself / return to infinite while loop
    }
}

基本的に、Controller クラスがこれOperationHandlerを初期化してstart()s します。いくつかの要求が到着するたびに、コントローラーはoperationRequiredスレッドで呼び出しを行い、操作が無限whileループで非同期に処理されるようにします。これを達成する方法はありますか?

this.wait()andを試してみましthis.notify()たが、デッドロックが発生するかIllegalMonitorStateException、さまざまな同期ブロックに依存します。

4

4 に答える 4

9

Javaスレッドに自分自身に通知させる方法は?

でブロックされているため、スレッド自体に通知することはできませんwait()。スレッドがロックしている同じオブジェクトを同期して を呼び出すことにより、別のスレッドにスレッドに通知させることができnotify()ます。サンプルについては、以下のコードを参照してください。

BlockingQueueとはいえ、この点でデータを共有するためにa を使用することをお勧めします。ロックとシグナリングのすべてを処理します。スレッドが行うのは呼び出しtake()だけで、次の操作がキューに追加されるのを待ちますput()

最後に、Runnable拡張する代わりに実装することを常にお勧めしThreadます。スレッドを実行可能にするとExecutorService、@Peter が回答で言及しているようにクラスを使用できます。コードを使用すると、ExecutorService次のようになります。

 public class OperationHandler implements Runnable {
     public void run() {
        // no looping or dequeuing needed
        // just execute the job
     }
 }

 // create a thread pool with a single thread worker
 ExecutorService threadPool = Executors.newSingleThreadExecutor();
 // or create a thread pool with 10 workers
 // ExecutorService threadPool = Executors.newFixedThreadPool(10);
 // or you can create an open-ended thread pool
 // ExecutorService threadPool = Executors.newCachedThreadPool();
 ...
 // do this once or many times
 threadPool.submit(new OperationHandler());
 ...

ただし、コードを調整して機能させたい場合は、次のようにします。

  private final Object lockObject = new Object();
  public void run() {
     synchronized (lockObject) {
        ...
        lockObject.wait();
     }
  }

  // called by another thread
  public void operationRequired() {
     synchronized (lockObject) {
        ...
        lockObject.notify();
     }
  }
于 2013-01-24T21:00:44.540 に答える
2

スレッドの wait()ing がないときに notify() すると、無視されます。つまり、待機と通知を同時に行うことはできないため、スレッドが自分自身に通知しても意味がありません。

キューとスレッドがある場合は、おそらく両方をラップする ExecutorService を使用する必要があります。ところで、BlockingQueueを使用します

于 2013-01-24T21:01:20.187 に答える
1

operationRequiredメソッドが待機中の場合、同じスレッドでメソッドを呼び出すことはできません。同じスレッド クラスにありますが、おそらく別のスレッドで実行されます。

したがって、通常の同期を使用します。最初にmonitorに入り、synchronized次にwaitまたはnotifyします。別のオプションは、キューフォームを使用することjava.util.concurrent.*です。彼らはこのことを内部的にサポートしています。

于 2013-01-24T21:02:11.277 に答える
0

UsaaBlockingQueueとそのtake()操作。すでに待機と通知が内部に埋め込まれています。

于 2013-01-25T10:07:11.170 に答える