Java Swing EDT & Concurrency

I'm just wondering if I still need to provide synchronization in invokeLater () Runnable.

I encountered a dead end and must overcome it while maintaining concurrency.

Will this be an example of good code ?:

private String text; private void updateText() { SwingUtilities.invokeLater(new Runnable() { public void run() { synchronized(FrameImpl.this) { someLabel.setText(text); } } }); } 

Sorry for the pretty bad example, but we must assume that text changed by different threads, cannot be entered and depends on the correct value.

Is this the right solution or will I inadvertently create a deadlock problem by sending the synchronized code to an unknown context ..?

Thanks.

+4
source share
2 answers

A better solution would be something like this:

 public class Whatever { private String text; private final Object TEXT_LOCK = new Object(); public void setText(final String newText) { synchronized (TEXT_LOCK) { text = newText; } SwingUtilities.invokeLater(new Runnable() { public void run() { someLabel.setText(newText); } }); } public String getText() { synchronized (TEXT_LOCK) { return text; } } } 

This ensures that if two threads try to call setText at the same time, they will not be compressed with each other. The first thread will be set to text and set the UI value with this value. The second thread will also set the value to text and start the second update of the user interface.

The end result is that the user interface will ultimately display the most recent text value, but the internal text variable will immediately contain the most recent value.

A few notes:

  • Using a separate locking object (i.e., TEXT_LOCK ) means that you are not vulnerable to code elsewhere that TEXT_LOCK monitor on the Whatever instance and inadvertently causes a deadlock. It's best to always keep tight control over your lock objects. It is also best to minimize the size of your synchronized blocks.
  • You can make the whole setText method synchronized, with the caveat that it makes you potentially vulnerable to a dead end, as mentioned above.
  • Reading the value of text also needs to be synchronized, although the Strings immutable. There are subtleties in the Java memory model, which means that you always need to synchronize around variables that can be read / written by multiple threads.

Check out Brian Goetz Java Concurrency in practice for a great dive into the complex parts of Concurrency (including the weirdness of the memory model).

+7
source

now that would be correct, all output from the task should be wrapped by ito InvokeLater (), another example for updating the GUI from BackGround tasks here

 private String text; private void updateText() { synchronized (FrameImpl.this) { SwingUtilities.invokeLater(new Runnable() { public void run() { someLabel.setText(text); } }); } } 
-2
source

All Articles