国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

長時間的GUI任務(wù)

這篇具有很好參考價值的文章主要介紹了長時間的GUI任務(wù)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

如果所有任務(wù)的執(zhí)行時間都較短(并且應(yīng)用程序中不包含執(zhí)行時間較長的非GUI部分),那么整個應(yīng)用程序都可以在事件線程內(nèi)部運行,并且完全不用關(guān)心線程。然而,在復(fù)雜的GUI?應(yīng)用程序中可能包含一些執(zhí)行時間較長的任務(wù),并且可能超過了用戶可以等待的時間,例如拼寫檢查、后臺編輯或者獲取遠(yuǎn)程資源等。這些任務(wù)必須在另一個線程中運行,才能使得GUI在運行時保持高響應(yīng)性。

Swing 使得在事件線程中運行任務(wù)更容易,但(在Java 6之前)并沒有提供任何機(jī)制來幫助GUI任務(wù)執(zhí)行其他線程中的代碼。然而在這里不需要借助于Swing:可以創(chuàng)建自己的Executor 來執(zhí)行長時間的任務(wù)。對于長時間的任務(wù),可以使用緩存線程池。只有GUI應(yīng)用程序很少會發(fā)起大量的長時間任務(wù),因此即使線程池可以無限制地增長也不會有太大的風(fēng)險。

首先來看一個簡單的任務(wù),該任務(wù)不支持取消操作和進(jìn)度指示,也不會在完成后更新GUI,我們之后再將這些功能依次添加進(jìn)來。在程序清單9-4中給出了一個與某個可視化組件綁定的監(jiān)聽器,它將一個長時間的任務(wù)提交給一個Executor。盡管有兩個層次的內(nèi)部類,但通過這種方式使某個GUI任務(wù)啟動另一個任務(wù)還是很簡單的:在事件線程中調(diào)用UI動作監(jiān)聽器,然后將一個Runnable提交到線程池中執(zhí)行。

這個示例通過“Fire and Forget”與方式將長時間任務(wù)從事件線程中分離出來,這種方式可能并不是非常有用。在執(zhí)行完一個長時間的任務(wù)后,通常會產(chǎn)生某種可視化的反饋。但你并不能從后臺線程中訪問這些表現(xiàn)對象,因此任務(wù)在完成時必須向事件線程提交另一個任務(wù)來更新用戶界面。

????????????????????????????????????程序清單9-4 ?????將一個長時間任務(wù)綁定到一個可視化組件 ????????

ExecutorService backgroundExec =Executors. newCachedThreadPool();

button,addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

backgroundExec. execute(new Runnable(){

public void run(){doBigComputation();}

} ) ?;

} } ) ;????????????????????????????????????????????????

程序清單9-5給出了如何實現(xiàn)這個功能的方式,但此時已經(jīng)開始變得復(fù)雜了,即已經(jīng)有了三層的內(nèi)部類。動作監(jiān)聽器首先使按鈕無效,并設(shè)置一個標(biāo)簽表示正在進(jìn)行某個計算,然后將一個任務(wù)提交給后臺的Executor。當(dāng)任務(wù)完成時,它會在事件線程中增加另一個任務(wù),該任務(wù)將重新激活按鈕并恢復(fù)標(biāo)簽文本。

???????????????????????????程序清單9-5支持用戶反饋的長時間任務(wù) ??????????????????????????????????????

button,addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

button. setEnabled(false);

label. setText("busy");

backgroundExec. execute(new Runnable(){

public void run(){

try {

doBigComputation();

}finally {

GuiExecutor. instance(). execute(new Runnable(){

public void run(){

button. setEnabled(true);

label. setText("idle");

}

} ) ?;

}

}

} ) ?;

} ?) ?;

??????????????????????????????????????????????????????????????????????

在按下按鈕時觸發(fā)的任務(wù)中包含3個連續(xù)的子任務(wù),它們將在事件線程與后臺線程之間交替運行。第一個子任務(wù)更新用戶界面,表示一個長時間的操作已經(jīng)開始,然后在后臺線程中啟動第二個子任務(wù)。當(dāng)?shù)诙€子任務(wù)完成時,它把第三個子任務(wù)再次提交到事件線程中運行,第三個子任務(wù)也會更新用戶界面來表示操作已經(jīng)完成。在GUI應(yīng)用程序中,這種“線程接力”是處理長時間任務(wù)的典型方法。

? 取消

當(dāng)某個任務(wù)在線程中運行了過長時間還沒有結(jié)束時,用戶可能希望取消它。你可以直接通過線程中斷來實現(xiàn)取消操作,但是一種更簡單的辦法是使用Future,專門用來管理可取消的任務(wù)。

如果調(diào)用Future的cancel方法,并將參數(shù)mayInterruptIfRunning設(shè)置為true,那么這個Future 可以中斷正在執(zhí)行任務(wù)的線程。如果你編寫的任務(wù)能夠響應(yīng)中斷,那么當(dāng)它被取消時就可以提前返回。在程序清單9-6給出的任務(wù)中,將輪詢線程的中斷狀態(tài),并且在發(fā)現(xiàn)中斷時提前返回。

??????????????????????????????????????????程序清單9-6 ?????????????????取消一個長時間任務(wù) ???????????

Future<?> ??runningTask=null;//線程封閉

startButton. addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

if (runningTask !=nul1){

runningTask =backgroundExec. submit(new Runnable(){

public void run(){

while (moreWork()){

if (Thread. currentThread(). isInterrupted()){

cleanUpPartialWork();

break;

}

doSomeWork();

}

}

} ) ?;

} ?;

} } ) ?;

cancelButton. addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent event){

if (runningTask !=null)

runningTask. cancel(true);

} } ) ?;

???????????????????????????????????????????????????????????????????????

由于runningTask被封閉在事件線程中,因此在對它進(jìn)行設(shè)置或檢查時不需要同步,并且“開始”按鈕的監(jiān)聽器可以確保每次只有一個后臺任務(wù)在運行。然而,當(dāng)任務(wù)完成時最好能通知按鈕監(jiān)聽器,例如說可以禁用“取消”按鈕。我們將在下一節(jié)解決這個問題。

?進(jìn)度標(biāo)識和完成標(biāo)識

通過Future 來表示一個長時間的任務(wù),可以極大地簡化取消操作的實現(xiàn)。在FutureTask中也有一個done 方法同樣有助于實現(xiàn)完成通知。當(dāng)后臺的Callable 完成后,將調(diào)用done。通過done 方法在事件線程中觸發(fā)一個完成任務(wù),我們能夠構(gòu)造一個BackgroundTask類,這個類將提供一個在事件線程中調(diào)用的onCompletion方法,如程序清單9-7所示。

?????????????????????程序清單9-7支持取消,完成通知以及進(jìn)度通知的后臺任務(wù)?????????????????????

abstract class BackgroundTask<V>implements Runnable, Future<V>{

private final FutureTask<V>computation =new Computation();

private class Computation extends FutureTask<V>{

public Computation(){

super(new Callable<V>(){

public v call() throws Exception {

return BackgroundTask. this. compute();

}

} ) ?;

}

protected final void done(){

GuiExecutor. instance(). execute(new Runnable(){

public void run(){

V value =null;

Throwable thrown =null;

boolean cancelled =false;

try {

value ?=get();

}catch (ExecutionException e){

thrown =e. getCause();

}catch (CancellationException e){

cancelled =true;

}catch (InterruptedException consumed){

}finally {

onCompletion(value, thrown, cancelled);

}

} ?;

} ) ?;

}

}

protected void setProgress(final int current, final int max){

GuiExecutor. instance(). execute(new Runnable(){

public void run(){onProgress(current, max);}

} ) ;

}

// ??在后臺線程中被取消

protected abstract v compute() throws Exception;

// ??在事件線程中被取消

protected void onCompletion(V result, Throwable exception,

boolean cancelled){}

protected void onProgress(int current, int max){}

// ??Future的其他方法

}

????????????????????????????????????????????????????????????????????

BackgroundTask還支持進(jìn)度標(biāo)識。compute 方法可以調(diào)用setProgress方法以數(shù)字形式來指示進(jìn)度。因而在事件線程中調(diào)用onProgress,從而更新用戶界面以顯示可視化的進(jìn)度信息。

要想實現(xiàn)BackgroundTask,你只需要實現(xiàn)compute,該方法將在后臺線程中調(diào)用。也可以改寫onCompletion和onProgress,這兩個方法也會在事件線程中調(diào)用。

基于FutureTask構(gòu)造的BackgroundTask 還能簡化取消操作。Compute不會檢查線程的中斷狀態(tài),而是調(diào)用Future. isCancelled。程序清單9-8 通過BackgroundTask重新實現(xiàn)了程序清單9-6中的示例程序。

???????????????程序清單9-8 ??通過BackgroundTask來執(zhí)行長時間的并且可取消的任務(wù) ??????????????

startButton. addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

class CancelListener implements ActionListener {

BackgroundTask<?>task;

public void actionPerformed(ActionEvent event){

if (task !=null)

task. cancel(true);

}

}

final CancelListen èr listener =new CancelListener();

listener. task =new BackgroundTask<Void>(){

public Void compute(){

while (moreWork()&&lisCancelled())

doSomeWork();

return null;

}

public void onCompletion(boolean cancelled, string s,

Throwable exception){

cancelButton. removeActionListener(listener);

label. setText("done");

}

} ?;

cancelButton. addActionListener(listener);

backgroundExec. execute(listener. task);

}

} ?) ?;

??????????????????????????????????????????????????????????????????????

SwingWorker

我們已經(jīng)通過FutureTask和Executor 構(gòu)建了一個簡單的框架,它會在后臺線程中執(zhí)行長時間的任務(wù),因此不會影響GUI的響應(yīng)性。在任何單線程的GUI框架都可以使用這些技術(shù),而不僅限于Swing。在Swing中,這里給出的許多特性是由SwingWorker類提供的,包括取消、完成通知、進(jìn)度指示等。在《The Swing Connection》和《The Java Tutorial》等資料中介紹了不同版本的SwingWorker,并在Java 6中包含了一個更新后的版本。文章來源地址http://www.zghlxwxcb.cn/news/detail-476314.html

到了這里,關(guān)于長時間的GUI任務(wù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包