1

クラスを使用して並行Javaでアクティブオブジェクトパターンを開発しようとしています。java.util.concurrent

とを使用して説明しClientますServer。サンプルServerは次のとおりです。

class Server implements Runnable {
  public final LinkedBlockingQueue que = new LinkedBlockingQueue();
  private final ExecutorService es = Executors.newCachedThreadPool();
  private Message currentMessage;

  private boolean state = false;

  public init() {
    es.submit(this);
  }

  public void requestForServer() {
    if (state) {
      this.currentMessage.await();
    }
    state = true;
  }

  public void run() {
     for(;;) {
       Message m = que.take();
       this.currentMessage = m;
       this.es.submit(m);           
     }
  }

}

そしてサンプルClient

class Client {

  private Server server;

  public Client(Server s) {
    this.server = s;
  }

  public void doSomething() {
    Message m = new Message(new Callable() {
      public Object call() {
        server.requestForServer();
      }
    });
    this.server.que.add(m);
  }

}

また、Messageカプセル化の例は次のとおりです。

class Message<V> extends FutureTask<V> {
  private Lock lock = new ReentrantLock();
  private Condition condition = new Condition();

  public Message(Callable<V> callable) {
    super(callable);
  }

  public void run() {
    try {
      lock.lock();
      super.run();
      lock.unlock();
    } catch(Exception e) {}
  }

  public void await() {
    try {
      condition.await();
    } catch(Exception e) {}
  }

  public void signal() {
    try {
      condition.signalAll();
    } catch(Exception e) {}
  }

}

そして、実行中のコードのサンプル:

Server s = new Server();
Client c = new Client (s);
s.init();
c.doSomething();

メッセージを伝えるために、実装の詳細をいくつか削除しました。

ここで問題となるServerstateは、の場合true、着信メッセージは待機する必要がありawait、現在のメッセージで呼び出されます。ただし、IllegalMonitorStateExceptionこれは、現在のメッセージが待機する現在のスレッドを所有していないことを意味します。Serverただし、現在のメッセージはとそのスレッドプールで呼び出されるため、現在のメッセージは現在の実行スレッドにもアクセスできるため、これは奇妙だと思います。

アイデアや提案、またはを使用したこのパターンの既知の実用的な実装に最も感謝しますjava.util.concurrent。前もって感謝します。

更新:このブログ投稿
で展開できるソリューションについて説明しました。お役に立てば幸いです。

4

1 に答える 1

3

対応する条件で待機するときに、実際にロックを取得する必要があります。そのロックがないと、条件に直接関連付けることはできません。これを実証するには:

  public void await() {
    lock.lock();
    try {
      condition.await();
    } catch(Exception e) {}
    finally{
      lock.unlock();
    }
  }

これでIllegalMonitorStateExceptionが解決されます

正しさの補足として、常にtry{}finally{}の方法でロックを解除する必要があります。例として私が書いたものを観察できます。この理由は、例外が発生し、lock().lock();呼び出さsuper.run(); lock.unlock()れない場合です。

于 2011-03-02T16:16:37.987 に答える