I'm afraid that this one is a little tricky since I couldn't recreate the issue in the example I wrote for this question (the example below works perfectly). Hopefully someone may have a clue as to possible problems with the actual application. I wrote a app with performs several long text operations. Each operation is done in its own thread. There is a Frame that is updated by the threads to let a user see how everything is progressing.
The problem is that the frame is displayed with all the updates that were sent to it only after all the threads are done with their jobs.
I've simplified the entire app into the code below but as I said the problem is that it works here. Any ideas are very welcome.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
private MyFrame frame;
private ExecutorService executorService;
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
main.startProcess();
}
public void startProcess() throws InterruptedException {
// Initialize the frame
frame = new MyFrame();
EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
// Initialize executorService for 3 threads and also 6 runnables
executorService = Executors.newFixedThreadPool(3);
MyRunnable runnable;
for(int i = 0; i < 6; i++) {
runnable = new MyRunnable(this, i);
executorService.execute(runnable);
}
// Start runnables
executorService.shutdown();
// Wait until all runnables are executed
while (!executorService.isTerminated()) {
Thread.sleep(10000);
}
// When all runnables are done close the frame
EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setVisible(false);
}
});
}
// Update the frame display
public synchronized void updateDisplay(final String update) {
EventQueue.invokeLater(new Runnable() {
public void run() {
frame.updateDisplay(update);
}
});
}
private class MyFrame extends JFrame {
private JPanel contentPane;
private JLabel lblDisplay;
public MyFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
lblDisplay = new JLabel("Display");
contentPane.add(lblDisplay, BorderLayout.CENTER);
pack();
}
public void updateDisplay(String update) {
lblDisplay.setText(update);
pack();
}
}
private class MyRunnable implements Runnable {
private int id;
private Main main;
public MyRunnable (Main main, int id) {
this.main = main;
this.id = id;
}
@Override
public void run() {
for(int i = 0; i < 3; i++) {
main.updateDisplay("Runnable " + id + " stepped " + i + " times.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}