從Sun聲明,ActionListener中的actionPerformed()會在EDT中自動執行,所以我決定在actionPerformed()方法中創建新線程,問題是這樣線程不在EDT內運行。有人可以解釋這個嗎?謝謝在actionPerformed和Event Dispatch Thread(EDT)問題中創建新線程
0
A
回答
3
如果您從EDT創建一個新線程,該線程與EDT不同。這不清楚嗎?
您應該通過EDT更新控件。
您可以爲繁重任務創建自己的後臺線程,但控件的更新只能通過EDT。 有一些構造可供您用來簡化代碼,例如通過Runnable
,由EDT通過SwingUtilities invoke Runnable撥打。你應該學習關於Concurrency in Swing
1
1)AWT或Swing GUI調用並創建EDT,本次活動是由做(也許還有其他)方法包(),並調用setVisible(真)
2)如果所有事件等待如果(EventQueue.isDispatchThread()){返回false,但EDT線程在那裏,直到當前的JVM實例存在爲止
3)如調用EDT隊列所述,您可以使用invokeLater或invokeAndWait,注意invokeAndWait只有當isDispatchThread返回false時才能使用,否則返回異常
4)通過從Swing Listener調用Thread.sleep(int)或其方法可以凍結和鎖定EDT,導致從事件隊列中丟失某些事件,
兩個代碼示例用於測試isDispatchThread()以及如何從Java對象
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class IsThereEDT {
private ScheduledExecutorService scheduler;
private AccurateScheduledRunnable periodic;
private ScheduledFuture<?> periodicMonitor;
private int taskPeriod = 30;
private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
private Date dateRun;
private JFrame frame1 = new JFrame("Frame 1");
public IsThereEDT() {
scheduler = Executors.newSingleThreadScheduledExecutor();
periodic = new AccurateScheduledRunnable() {
private final int ALLOWED_TARDINESS = 200;
private int countRun = 0;
private int countCalled = 0;
private int maxCalled = 10;
@Override
public void run() {
countCalled++;
if (countCalled < maxCalled) {
if (countCalled % 3 == 0) {
/*if (EventQueue.isDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
//some stuff
}
});
} else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
//some stuff
}
});
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
}*/
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Push a new event to EDT");
frame1.repaint();
isThereReallyEDT();
}
});
} else {
if (this.getExecutionTime() < ALLOWED_TARDINESS) {
countRun++;
isThereReallyEDT(); // non on EDT
}
}
} else {
System.out.println("Terminating this madness");
System.exit(0);
}
}
};
periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
periodic.setThreadMonitor(periodicMonitor);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
isThereReallyEDT();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.getContentPane().add(new JLabel("Hello in frame 1"));
frame1.pack();
frame1.setLocation(100, 100);
frame1.setVisible(true);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame2 = new JFrame("Frame 2");
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.getContentPane().add(new JLabel("Hello in frame 2"));
frame2.pack();
frame2.setLocation(200, 200);
frame2.setVisible(true);
isThereReallyEDT();
}
});
}
private void isThereReallyEDT() {
dateRun = new java.util.Date();
System.out.println(" Time at : " + sdf.format(dateRun));
if (EventQueue.isDispatchThread()) {
System.out.println("EventQueue.isDispatchThread");
} else {
System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
}
if (SwingUtilities.isEventDispatchThread()) {
System.out.println("SwingUtilities.isEventDispatchThread");
} else {
System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
}
System.out.println();
}
public static void main(String[] args) {
IsThereEDT isdt = new IsThereEDT();
}
}
abstract class AccurateScheduledRunnable implements Runnable {
private ScheduledFuture<?> thisThreadsMonitor;
public void setThreadMonitor(ScheduledFuture<?> monitor) {
this.thisThreadsMonitor = monitor;
}
protected long getExecutionTime() {
long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
return delay;
}
}
和簡單的代碼
。
。
import java.awt.EventQueue;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class IsThereEDT {
private ScheduledExecutorService scheduler;
private AccurateScheduledRunnable periodic;
private ScheduledFuture<?> periodicMonitor;
private int taskPeriod = 30;
private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
private Date dateRun;
private JFrame frame1 = new JFrame("Frame 1");
public IsThereEDT() {
scheduler = Executors.newSingleThreadScheduledExecutor();
periodic = new AccurateScheduledRunnable() {
private final int ALLOWED_TARDINESS = 200;
private int countRun = 0;
private int countCalled = 0;
private int maxCalled = 10;
@Override
public void run() {
countCalled++;
if (countCalled < maxCalled) {
if (countCalled % 3 == 0) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Push a new event to EDT");
frame1.repaint();
isThereReallyEDT();
}
});
} else {
if (this.getExecutionTime() < ALLOWED_TARDINESS) {
countRun++;
isThereReallyEDT(); // non on EDT
}
}
} else {
System.out.println("Terminating this madness");
System.exit(0);
}
}
};
periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
periodic.setThreadMonitor(periodicMonitor);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
isThereReallyEDT();
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.getContentPane().add(new JLabel("Hello in frame 1"));
frame1.pack();
frame1.setLocation(100, 100);
frame1.setVisible(true);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame2 = new JFrame("Frame 2");
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.getContentPane().add(new JLabel("Hello in frame 2"));
frame2.pack();
frame2.setLocation(200, 200);
frame2.setVisible(true);
isThereReallyEDT();
}
});
}
private void isThereReallyEDT() {
dateRun = new java.util.Date();
System.out.println(" Time at : " + sdf.format(dateRun));
if (EventQueue.isDispatchThread()) {
System.out.println("EventQueue.isDispatchThread");
} else {
System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
}
if (SwingUtilities.isEventDispatchThread()) {
System.out.println("SwingUtilities.isEventDispatchThread");
} else {
System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
}
System.out.println();
}
public static void main(String[] args) {
IsThereEDT isdt = new IsThereEDT();
}
}
abstract class AccurateScheduledRunnable implements Runnable {
private ScheduledFuture<?> thisThreadsMonitor;
public void setThreadMonitor(ScheduledFuture<?> monitor) {
this.thisThreadsMonitor = monitor;
}
protected long getExecutionTime() {
long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
return delay;
}
}
相關問題
- 1. 在JApplet中正確使用Event Dispatch Thread?
- 2. 代碼是否應該由EDT(Event Dispatch Thread)執行或不執行?
- 3. jcombobox actionperformed event
- 4. Android線程問題Thread-387
- 5. JDI Event Dispatch nullpointerexception
- 6. 爲什麼PyDev中的Swing Event Dispatch Thread沒有斷點?
- 7. 如何在Event dispatch線程中同時運行兩個組件?
- 8. JOptionPane.showMessageDialog和swing.utils.invokeAndWait的(event-dispatch)線程安全用法是什麼?
- 9. 只顯示Event-Dispatch線程中最後添加的JPanel到JFrame
- 10. ScheduledExecutorService Thread創建多個線程
- 11. 現有線程創建使用新的Thread()一個新的線程。開始()
- 12. 讓線程在EDT的非EDT(事件調度線程)線程上運行
- 13. Java EE「JDI Event Dispatch」錯誤
- 14. 在循環中創建JProgressBar更新值的問題(線程化)
- 15. 在新線程中創建對話框
- 16. AspectJ EDT-Checker代碼問題
- 17. 在線程中創建變量和傳遞指針的問題
- 18. actionPerformed(ActionEvent e)是否運行在與事件派發線程(EDT)不同的線程中?
- 19. 使用Runnable和Thread創建線程的區別?
- 20. 主線程和當前Thread
- 21. nfc intent dispatch問題
- 22. EDT擺動問題
- 23. 創建線程問題的Enif_send函數
- 24. WPF RichTextBox文檔創建線程問題
- 25. 創建Thread類
- 26. 創建參數化線程的問題
- 27. Grand Central Dispatch中的線程數和線程數
- 28. Grand Central Dispatch應該創建多少個線程?
- 29. 在actionperformed偵聽器中創建jpanel?
- 30. 在新窗口中創建線程C++
'invokeAndWait'是不可能從'的actionPerformed()'運行,因爲這個線程可能在'EDT'結束,然後返回了幾個'exception',沒有好的建議 – mKorbel 2012-04-22 09:09:44
您好我知道控制更新應該在EDT內部。我只是認爲新創建的線程會分享EDT,因爲它已經在EDT環境內部了。< – MinhHoang 2012-04-22 09:10:39
@mKorbel:好點。但我懷疑他想爲某個任務創建後臺線程,然後更新GUI,這是通常的進入Swing的錯誤。我將更新答案以澄清此問題。 – Cratylus 2012-04-22 09:10:58