【问题标题】:Active Object Pattern in Concurrent Java 1.5+并发 Java 1.5+ 中的活动对象模式
【发布时间】:2011-03-02 10:58:38
【问题描述】:

我正在尝试使用 java.util.concurrent 类在并发 Java 中开发 active object pattern

我使用ClientServer 来描述它。示例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();

我删除了一些实现细节来传达我的信息。

现在,问题在于Server 中的statetrue,因此传入的消息应该等待并且在当前消息上调用await。但是,我得到IllegalMonitorStateException,这意味着当前消息不拥有当前线程来等待它。但是,我认为这很奇怪,因为当前消息在 Server 及其线程池中被调用,因此当前消息也可以访问当前执行线程。

如果您有任何想法或建议,或者使用java.util.concurrent 对此模式的已知有效实现,我将不胜感激。提前致谢。

更新
我在blog post 中讨论了我可以部署的解决方案。我希望它可以帮助。

【问题讨论】:

    标签: java concurrency concurrent-programming java.util.concurrent


    【解决方案1】:

    当您等待相应条件时,您必须实际获取锁。没有那个锁,你就不能直接将自己与条件联系起来。为了证明这一点:

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

    这应该可以解决您的 IllegalMonitorStateException

    关于正确性,您应该始终以 try{ } finally{ } 方式释放锁,您可以观察我作为示例编写的内容。原因是如果lock().lock();super.run(); 之间发生异常,则永远不会调用lock.unlock()

    【讨论】:

    • @john-v 感谢您的回复。但是,这并不能解决问题,我认为不这样做是有道理的,因为这个想法只是替换了锁定的位置。
    • @Berooz 您是否仍然收到 IllegalMonitorStateException 或者您是否收到其他异常?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    相关资源
    最近更新 更多