この質問のために書いた例では問題を再現できなかったため、これは少し難しいと思います(以下の例は完全に機能します)。実際のアプリケーションで起こりうる問題について、誰かが手がかりを持っていることを願っています。いくつかの長いテキスト操作を実行するアプリを作成しました。各操作は、独自のスレッドで実行されます。ユーザーがすべての進行状況を確認できるように、スレッドによって更新される Frame があります。
問題は、すべてのスレッドがジョブを完了した後にのみ、送信されたすべての更新とともにフレームが表示されることです。
アプリ全体を以下のコードに単純化しましたが、問題はここで機能することです。どんなアイデアでも大歓迎です。
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();
}
}
}
}
}