SwingUtilities提供兩個(gè)方法
Java Swing GUI多線程之SwingUtilities.invokeLater和invokeAndWait在Java中Swing是線程不安全的,是單線程的設(shè)計(jì),這樣的造成結(jié)果就是:只能從事件派發(fā)線程訪問將要在屏幕上繪制的Swing組件。事件派發(fā)線程是調(diào)用paint和update等回調(diào)方法的線程,它還是事件監(jiān)聽器接口中定義的事件處理方法,例如,ActionListener中的actionPerformed方法在事件派發(fā)線程中調(diào)用。
Swing是事件驅(qū)動(dòng)的,所以在回調(diào)函數(shù)中更新可見的GUI是很自然的事情,比如,有一個(gè)按鈕被按下,項(xiàng)目列表需要更新時(shí),則通常在與該按鈕相關(guān)聯(lián)的事件監(jiān)聽器的actionPerformed方法中來實(shí)現(xiàn)該列表的更新,從事件派發(fā)線程以外的線程中更新Swing組件是不正常的。
有時(shí)需要從事件派發(fā)線程以外的線程中更新Swing組件,例如,在actionPerformed中有很費(fèi)時(shí)的操作,需要很長(zhǎng)時(shí)間才能返回,按鈕激活后需要很長(zhǎng)時(shí)間才能看到更新的列表,按鈕會(huì)長(zhǎng)時(shí)間保持按下的狀態(tài)只到actionPerformed返回,一般說來耗時(shí)的操作不應(yīng)該在事件處理方法中執(zhí)行,因?yàn)槭录幚矸祷刂?,其他事件是不能觸發(fā)的,界面類似于卡住的狀況,所以在獨(dú)立的線程上執(zhí)行比較耗時(shí)的操作可能更好,這會(huì)立即更新用戶界面和釋放事件派發(fā)線程去派發(fā)其他的事件。
SwingUtilities類提供了兩個(gè)方法:invokeLate和invoteAndWait,它們都使事件派發(fā)線程上的可運(yùn)行對(duì)象排隊(duì)。當(dāng)可運(yùn)行對(duì)象排在事件派發(fā)隊(duì)列的隊(duì)首時(shí),就調(diào)用其run方法。其效果是允許事件派發(fā)線程調(diào)用另一個(gè)線程中的任意一個(gè)代碼塊。
- startButton.addActionListener(new ActionListener())
- {
- public void actionPerformed(ActionEvent e)
- {
- GetInfoThread t = new GetInfoThread(Test.this);
- t.start();
- startButton.setEnabled(false);
- }
- }
- class GetInfoThread extends Thread
- {
- Test applet;
- public GetInfoThread(Test applet)
- {
- this.applet = applet;
- }
- public void run()
- {
- while (true)
- {
- try
- {
- Thread.sleep(500);
- applet.getProgressBar().setValue(Math.random() * 100);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- }
- }
invokeLater和invoikeAndWait的一個(gè)重要區(qū)別:可以從事件派發(fā)線程中調(diào)用invokeLater,卻不能從事件派發(fā)線程中調(diào)用 invokeAndWait,從事件派發(fā)線程調(diào)用invokeAndWait的問題是:invokeAndWait鎖定調(diào)用它的線程,直到可運(yùn)行對(duì)象從事件派發(fā)線程中派發(fā)出去并且該可運(yùn)行的對(duì)象的run方法激活,如果從事件派發(fā)線程調(diào)用invoikeAndWait,則會(huì)發(fā)生死鎖的狀況,因?yàn)?invokeAndWait正在等待事件派發(fā),但是,由于是從事件派發(fā)線程中調(diào)用invokeAndWait,所以直到invokeAndWait返回后事件才能派發(fā)。
actionPerformed();返回的時(shí)候事件派發(fā)線程才能派發(fā)線程,而在actionPerformed中使用invokeAndWait則會(huì)導(dǎo)致actionPerformed不能返回。所以也就無法派發(fā)invokeAndWait中的線程。
由于Swing是線程不安全的,所以,從事件派發(fā)線程之外的線程訪問Swing組件是不安全的,SwingUtilities類提供這兩種方法用于執(zhí)行事件派發(fā)線程中的代碼
總結(jié): GUI中多線調(diào)用方法應(yīng)該使用:SwingUtilities.invokeLater和invokeAndWait 而不是普通情況下那樣應(yīng)用.