Reputation: 468
I'm having trouble trying to understand why manipulating a swing component, namely a JProgressBar
, just before waiting for a parallel task to finish.
In the following example, the progressBar will only activate its indeterminate mode after the thread finishes waiting for the result of a Callable
, even though (I expect) that the call for setIndeterminate(true)
happens before the waiting. Can someone explain why this happens?
private void thisDoesntWork(JProgressBar p){
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> jobResult = executor.submit(() -> aLengthyJob());
// This happens only after the button finishes waiting. (future.get())
// I want to know why. Shouldn't this line happen before the thread blocks?
p.setIndeterminate(true);
try {
System.out.println(jobResult.get());
} catch (InterruptedException | ExecutionException ex) {}
}
public void createAndShowGUI(){
JFrame frame = new JFrame("This progress bar wont work");
JPanel panel = new JPanel();
JButton button = new JButton("Start");
JProgressBar progressBar = new JProgressBar();
frame.setSize(500, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
// Problem happens withing this button's action
button.addActionListener((e)->{
thisDoesntWork(progressBar);
});
panel.add(button);
panel.add(progressBar);
frame.add(panel);
frame.setVisible(true);
}
private String aLengthyJob(){
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {}
return "Done";
}
public static void main(String[] args) {
new Test().createAndShowGUI();
}
If the waiting happens in another thread, it works as expected.
// Waiting in a third thread works fine
private void thisWorks(JButton b, JProgressBar p) {
p.setIndeterminate(true);
b.setEnabled(false);
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> jobResult;
jobResult = executor.submit(() -> aLengthyJob());
executor.execute(() -> {
try {
System.out.println(jobResult.get());
p.setIndeterminate(false);
b.setEnabled(true);
} catch (InterruptedException | ExecutionException ex) {}
});
}
Imports:
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
Upvotes: 0
Views: 81
Reputation: 15622
jobResult.get()
waits for the end of the other thread inside the EDT, blocking it.
Maybe you want to at least link to some background on edt.– GhostCat
here are some resouces to read about the EDT:
https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
What is the event dispatching thread?
Upvotes: 4