Thread-confinement/swingworkers
I am not clear about thread confinement. In swing all the gui components must be updated through the EDT. SwingWorker is provided in Java6 for lengthy operations, and in the done method the gui components can be updated. My understanding was that the gui components in the done() method are updated in the EDT. Therefore there should be no synchronization problems. But here link text
it says:
Because the ImageRetriever class will download an image and 开发者_StackOverflow社区place it on a large label, providing the label and image URL in the constructor is convenient. ImageRetriever needs the URL to retrieve an image. Provide the label so that the ImageRetriever instance can set the label's icon itself. If you use inner classes, you might not even provide this information in the constructor, because the worker thread will be able to access the information directly. However, providing the information in the constructor helps your application to be more thread-safe because that information will not be shared among ImageRetriever instances
I am confused on this. If the SwingWorker methods update the gui components (in the example of the link the JLabel) in the EDT, why is it more thread-safe to not share them among ImageRetriever(=SwingWorker) instances? If we have multiple SwingWorkers and in the done() method they update the same component, we must use synchronization primitives for the update? Am I missunderstanding something? Doesn't thread-confinement mean that only 1 thread will do all the actions? Aren't swingworkers thread-confined?
Thanks
If the label is declared in the parent class and for some reason a new value is assigned to that variable at some point, then all the swingworkers will see the update. Because this might happen while the EDT is updating things, it can lead to weird behaviors.
For instance:
SW in EDT - label.setText(...);
Thread1 - label = new JLabel();
SW in EDT - label.setIcon(...);
If the label variable is shared you will get an inconsistent state (label without text or icon).
Update Storing the label as a variable passed through the constructors is a way to avoid this issue. If you want to see changes but not in the middle of a method execution, on way is to use a method local variable. You assign it at the beginning of the method to make sure it's not going to be changed outside.
If you use inner classes and the attribute of the parent class this will look like this:
public void done() {
JLabel l = label;
l.setText(...);
l.setIcon(...);
}
If the variable is defined as an attribute of the SW, you will have to create some way of getting the value stored in the main class (eg. a getter)
精彩评论