Java 如何从Swing Gui访问同步缓冲区?

Java 如何从Swing Gui访问同步缓冲区?,java,multithreading,swing,user-interface,synchronization,Java,Multithreading,Swing,User Interface,Synchronization,我必须编写一个GUI应用程序,使用RMI在多个客户端之间保持一致的状态 因为RMI调用将阻塞,所以我将它们与GUI线程放在一个单独的线程中。 要在GUI线程之间推送信息,我的第一个想法是使用同步缓冲区 但是如果我在缓冲区上调用同步方法,GUI将冻结。如果我不使用synchronized关键字,缓冲区就不会是线程安全的 从Java文档: 同一对象上的两个同步方法调用不可能交错。当一个线程为一个对象执行同步方法时,调用同一对象块的同步方法的所有其他线程(暂停执行),直到第一个线程对该对象执行完毕 是

我必须编写一个GUI应用程序,使用RMI在多个客户端之间保持一致的状态

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

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

从Java文档:

同一对象上的两个同步方法调用不可能交错。当一个线程为一个对象执行同步方法时,调用同一对象块的同步方法的所有其他线程(暂停执行),直到第一个线程对该对象执行完毕


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

一种方法是使用、显示和将模型数据从视图中分离出来。在最后一个示例中,模型在后台线程上演化,并且使用
javax.swing.Timer
定期更新视图<代码>SwingWorker,如图所示,是另一种选择。

您可以尝试多种方法

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


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

查看
java.util.concurrent
中的任何对象是否会起作用。它们提供了比
synchronized
更细粒度的控制

例如,下面是使用
信号灯可以做的事情:

在某些共享类中

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.
// 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线程中

// 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.
// 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线程不能保证看到每一次更新,但是如果RMI线程没有持续更新状态,它应该可以工作。

如果从工作线程调用缓冲区上的方法,我认为它不应该冻结GUI。除非我遗漏了什么。请解释你为什么不这么认为。@hoverfullofeels我想他指的是用户界面,在某个阶段,必须尝试从缓冲区读取。听起来像是SwingWorker的工作,Mad:但这正是我的观点。如果他使用SwingWorker或任何后台工作线程,这将如何与Swing事件线程EDT联系起来?@HovercraftFullOfEels我认为他在设计中没有走那么远;)