恐怕这个有点棘手,因为我无法在我为这个问题编写的示例中重新创建问题(下面的示例完美运行)。希望有人可能对实际应用程序可能存在的问题有所了解。我编写了一个执行几个长文本操作的应用程序。每个操作都在自己的线程中完成。有一个由线程更新的框架,让用户看到一切进展如何。
问题在于,只有在所有线程都完成了它们的工作之后,框架才会显示发送给它的所有更新。
我已将整个应用程序简化为下面的代码,但正如我所说的,问题在于它可以在这里工作。任何想法都非常受欢迎。
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();
}
}
}
}
}