當您使用AWT或Swing時,會在後臺運行一個特殊線程,稱爲EventQueue。當你將一個監聽器添加到一個組件(比如ActionListener到JButton)和事件監聽器方法(比如actionPerformed)時,該方法在EventQueue線程上執行。您可以選擇到EventQueue線程上執行的東西時,當前線程是無法通過運行
EventQueue.invokeLater(new Runnable(){ //this could also be SwingUtilities.invokeLater() instead
public void run(){
...
}
});
這是偉大的EventQueue上線。當你一遍又一遍地發生一個事件時,問題就來了。發生這種情況時,EventQueue線程無法足夠快地爲前一個事件執行代碼,以執行下一個事件的代碼。所以它將事件放入隊列中,等待當前的事件處理程序完成。當您在EventQueue線程上執行大型操作時(例如從文件讀取),可能會發生這種情況。例如:
ActionListener l = new ActionListener(){
public void actionPerformed(ActionEvent ae){
try {
BufferedReader in = new BufferedReader(new FileReader("foo.txt"));
StringBuffer sb = new StringBuffer();
char[] buf = new char[4096];
int n;
while (-1 != (n = in.read(buf))){
sb.append(buf, 0, n);
}
in.close();
String s = sb.toString();
jTextPane1.setText(s);
} catch (IOException ioe){
ioe.printStackTrace();
}
}
};
jButton1.addActionListener(l);
內actionPerformed
所有代碼都是EventQueue中線程上執行。在代碼完成之前,不能處理其他事件。如果foo.txt是一個大文件,那麼在代碼完成之前還需要一段時間。這意味着每次在代碼完成之前單擊jButton1
時,它都會將新事件添加到EventQueue。所以如果你反覆點擊jButton1
,那麼會有越來越多的事件添加到隊列中。你不能以這種方式溢出,因爲你不能夠快速點擊,並且不會放棄足夠長的時間。但是,如果鼠標移動等事件發生在每個像素處,則會導致重大事件。然後,這可能會導致一個巨大的EventQueue隊列,甚至可能導致EventQueue溢出。解決此問題的一種方法可能是在事件發生後立即啓動另一個線程。例如:
final Runnable r = new Runnable() {
public void run() {
try {
BufferedReader in = new BufferedReader(new FileReader("foo.txt"));
StringBuffer sb = new StringBuffer();
char[] buf = new char[4096];
int n;
while (-1 != (n = in.read(buf))) {
sb.append(buf, 0, n);
}
in.close();
final String s = sb.toString();
EventQueue.invokeLater(new Runnable(){
public void run(){
jTextPane1.setText(s);
}
});
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
};
ActionListener l = new ActionListener(){
public void actionPerformed(ActionEvent ae){
new Thread(r).start();
}
};
jButton1.addActionListener(l);
有必要的理由來調用EventQueue中的線程上的東西,比如在
EventQueue.invokeLater(new Runnable(){
public void run(){
jTextPane1.setText(s);
}
});
是因爲否則屏幕不會被更新。例如,如果維護進度條,EventQueue.invokeLater()
會立即更新屏幕,但是如果未包裝在EventQueue.invokeLater()
中,則它將等待直到線程完成,然後更新屏幕。當談到進度條時,這是毫無用處的。在這種情況下,它可能沒有太大的作用。
Thanx爲一個偉大的問題!
感謝您的回答!你很徹底。我的問題是關於Java ME,而不是Java SE。然而,使用EventQueue的想法在兩者中看起來都是一樣的。不幸的是,答案仍然不能解決我目前的** J2ME **問題。我會忍受你所說的話,並會嘗試自己解決它。 – 2010-09-12 15:16:18
好吧,這是一個僵局,即使NetBeans找不到一個。 – 2010-09-12 16:18:22