2

I am currently refactoring an application I made to be thread safe.

I have a JCheckBox that I need to check. This JCheckBox is referenced throughout the program in various different threads.

Can I simply call checkbox.isSelected() or do I have to make this call using invokeLater?

I'm finding it difficult to understand concurrency in general, but I'm getting there slowly but surely. If this is a stupid question, please tell me why so I can better my understanding.

Thank you.

DCON
  • 628
  • 5
  • 18
  • I'm not entirely certain, but considering isSelected() should purely return a value without changing the checkbox, you should be fine without the use of invokeLater. – Lewis_McReu May 17 '17 at 11:20
  • just given [this answer](http://stackoverflow.com/a/1796687/1799530), i´d say no – SomeJavaGuy May 17 '17 at 11:23
  • Are you calling `isSelected()` outside of the `EDT`? If you're doing some processing in an action listener for example, there's no problem. If you're calling `isSelected()` from regular code, then I'd say that's more of a design issue and `invokeLater()` wouldn't be a very suitable way to fix it anyway. – Kayaman May 17 '17 at 11:50
  • As I stated in the question, yes, I am calling this method on the same checkbox in various different threads. I need to see whether or not the checkbox is selected to decide what calculations need to be performed. It would probably be better to store the value of the checkbox and pass it in as a parameter to the method performing the calculations instead of referencing the checkbox each time... yes? – DCON May 17 '17 at 11:53
  • 1
    Probably yes. I'd imagine that you start some kind of processing at which point you need to check what settings were made. So when pressing a button or whatever, you'd gather the settings, store them in an object and then start the processing using that object, ignoring what's happening in the GUI during that time. – Kayaman May 17 '17 at 12:04

1 Answers1

1

No, it's not thread safe. Swing generally is not thread safe. You need to use invokeLater. On the other hand, you can make the current thread wait until the task ininvokeLater finishes:

private boolean isSelected(final AbstractButton button) {
    if (SwingUtilities.isEventDispatchThread()) {
        // a shortcut so the AWT thread won't wait for itself
        return button.isSelected();
    }
    final AtomicBoolean isSelected = new AtomicBoolean();
    final CountDownLatch latch = new CountDownLatch(1);
    SwingUtilities.invokeLater(() -> {
        try {
            isSelected.set(button.isSelected());
        } finally {
            latch.countDown();
        }
    });
    try {
        latch.await();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    return isSelected.get();
}
Tamas Rev
  • 7,008
  • 5
  • 32
  • 49