3

実行中の 2 つのメイン スレッド A と B と、非同期に呼び出される 1 つのスレッド T があるとします。スレッド T でメッセージ aMsg を受信するまでスレッド A を待機させ、スレッド T でメッセージ msgB を受信するまでスレッド B を停止させたいとします。 2つのセンパフォアでこれを行う方法を知っています:

sempahoreA = new Sempahore(0);
sempahoreB = new Sempahore(0);

//in thread A
//code until where to run 
semaphoreA.acquire()

//in thread B
//code until where to run 
semaphoreB.acquire()

//in thread T
if (msgA.equals(msgRecevied)) {
    semaphoreA.release()
} 
if (msgB.equals(msgReceived)) {
    semaphoreB.release()
}

問題は、複数の A、B、C、... スレッドがあり、複数のセマフォを使用したくないことです。java.util.concurrentすべてのセマフォを 1 つのインスタンスだけに置き換えることができるクラスはどこかにありますか?

synchronizer = //?

//in thread A
//code until where to run 
synchronizer.acquire(msgA)//only let go if msgA is received from thread calling release

//in thread B
//code until where to run 
synchronizer.acquire(msgB)//only let go if msgA is received from thread calling release

//in thread T
if (msgA.equals(msgRecevied)) {
    synchronizer.release(msgA)
} 
if (msgB.equals(msgReceived)) {
    synchronizer.release(msgB)
}//actually here you can call synchronizer.release(msgReceived)
4

1 に答える 1

2

すごい直感m3th0dman。あなたが探しているのはTransfer Queueと呼ばれるものだと思います。

これは「プロデューサーがコンシューマーが要素を受け取るのを待つことができる BlockingQueue」です。あなたの場合、スレッド A と B はプロデューサーであり、スレッド T は唯一のコンシューマーです。

手短に:

  1. 共有を作成するTransferQueue<Object> synchronizer = new TransferQueue<>();
  2. スレッド A と B はブロッキング メソッドを呼び出しますsynchronizer.transfer(new Object());
  3. 一方、Thread t はsynchronizer.take();暇なときにブロックを解除するように呼び出します。

次に例を示します。

import java.util.concurrent.TransferQueue;

public class TransferQueueExample {
    public static void main(String[] args) {
        final TransferQueue<Object> synchronizer = new TransferQueue<>();

        for (int i = 0; i < 10; i++) {
            final Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    // Do work until
                    // ...
                    System.out.println("Thread " + i + " is transferring.");

                    synchronizer.transfer(new Object()); // This is blocking
                    System.out.println("Thread " + i + " done transferring.");
                }
            }).start();
        }

        final Thread consumer = new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO: Note thatthis will run indefinitely so in a real
                // scenario, find a way of shutting this thread down.
                while (true) {
                    System.out.println("There are about " +
                                       synchronizer.getWaitingConsumerCount()
                                       + " threads waiting");
                    synchronizer.take();
                    System.sleep(1000);
                }
            }
        }).start();
    }
}

入れ子クラスと無名クラスが邪魔にならないことを願っています。

于 2013-11-08T04:55:40.473 に答える