2

我必须编写一个使用 RMI 的 GUI 应用程序来跨多个客户端保持一致的状态。

因为 RMI 调用会阻塞,所以我将它们放在与 GUI 线程不同的线程中。要将信息推送到 GUI 线程和从 GUI 线程推送信息,我的第一个想法是使用同步缓冲区。

但是如果我在 Buffer 上调用同步方法,GUI 将冻结。如果我不使用 synchronized 关键字,缓冲区将不是线程安全的。

来自 Java 文档:

同一对象上的同步方法的两次调用不可能交错。当一个线程正在为一个对象执行同步方法时,所有其他为同一对象调用同步方法的线程都会阻塞(暂停执行),直到第一个线程处理完该对象。

是否有其他替代方法可以使缓冲区线程安全并且不会冻结 GUI。

4

3 回答 3

3

一种方法是使用 模型-视图-控制器模式将模型数据从视图中分离出来,显示在此处此处此处。在最后一个示例中,模型在后台线程上演化,视图使用javax.swing.Timer. SwingWorker,如图所示是另一种选择。

于 2012-08-27T02:39:03.737 回答
2

您可以尝试多种方法。

您可以从 RMI/读取线程触发一个事件,该事件可用于通知 UI 更改。只需确保只更新 EDT 中的 UI。

您可以使用SwingWorker在后台处理 RMI 请求,并使用publish`process` 方法将结果同步回客户端。

于 2012-08-27T02:40:32.680 回答
2

看看是否有任何对象java.util.concurrent可以解决问题。它们提供比synchronized.

例如,您可以使用 a 执行以下操作Semaphore

在一些共享课程中

public class Shared {
  public final Semaphore mutex = new Semaphore(1);
}

在 RMI 线程中

// synchronizing with other clients...
// now we're at the critical section.  Block until we have the lock
Shared.mutex.acquireUninterruptibly();
// update state
Shared.mutex.release();
// critical section over.  Schedule an update on the GUI thread.

在 GUI 线程中

// if the critical section is free, check for updated state.  Else, just wait
if (Shared.mutex.tryAcquire())  {
   try {
     // read state and update GUI
   } finally {
     Shared.mutex.release();
   }
}

在这里,GUI 线程不能保证看到每一个更新,但如果 R​​MI 线程不是不断更新状态,它应该可以工作。

于 2012-08-27T04:23:06.240 回答