Шаблон активного объекта в параллельной Java 1.5+ - PullRequest
1 голос
/ 02 марта 2011

Я пытаюсь разработать шаблон активного объекта в параллельной 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.Заранее спасибо.

ОБНОВЛЕНИЕ :
Я обсуждал решение, которое мог бы развернуть в этом сообщении в блоге .Я надеюсь, что это может помочь.

1 Ответ

3 голосов
/ 02 марта 2011

Вы должны фактически получить замок, когда ожидаете соответствующего состояния. Без этой блокировки вы не можете напрямую связать себя с этим условием. Чтобы продемонстрировать это:

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

Это должно разрешить ваше IllegalMonitorStateException

В дополнение к правильности, вы всегда должны снимать блокировку попыткой {} finally {}, вы можете посмотреть, что я написал в качестве примера. Причина этого заключается в том, что если исключение возникает между lock().lock(); и super.run(); lock.unlock(), оно никогда не будет вызвано.

...