Reputation: 456
I have to write a GUI application that uses RMI to keep consistent state across multiple clients.
Because the RMI calls will block, I put them in a separate thread from the GUI thread. To push information to and from the GUI thread my first thought was to use a synchronized buffer.
But if I call a synchronized method on the Buffer, the GUI will freeze. If I don't use the synchronized keyword the Buffer won't be thread safe.
From the Java Docs:
It is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Is there some other alternative that will make the buffer thread safe and not freeze the GUI.
Upvotes: 2
Views: 419
Reputation: 24523
See if any of the objects in java.util.concurrent
would do the trick. They offer more fine-grained control than synchronized
.
For example, here's what you could do with a Semaphore
:
In some shared class
public class Shared {
public final Semaphore mutex = new Semaphore(1);
}
In the RMI thread
// 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.
In 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();
}
}
Here, the GUI thread is not guaranteed to see every single update, but if the RMI thread isn't constantly updating state it should work.
Upvotes: 2
Reputation: 347314
You have a number of approaches you could try.
You could fire an event from the RMI/read thread that can be used to notify the UI of changes. Just make sure that you only update the UI in the EDT.
You could use a SwingWorker to process the RMI requests in the background and the publish
`process` methods to sync the results back to the client.
Upvotes: 2
Reputation: 205875
One approach is to separate the model data from the view using the Model–View–Controller pattern, shown here, here and here. In the last example, the model evolves on a background thread and the view is periodically updated using a javax.swing.Timer
. SwingWorker
, illustrated here, is an alternative.
Upvotes: 3