最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

正確結(jié)束Java線程的方法

 更新時(shí)間:2019年05月31日 15:07:43   作者:展翅而飛  
線程的啟動(dòng)很簡(jiǎn)單,但用戶可能隨時(shí)取消任務(wù),怎么樣讓跑起來(lái)的線程正確地結(jié)束,這是今天要討論的話題。下面小編來(lái)和大家一起學(xué)習(xí)一下吧

使用標(biāo)志位

很簡(jiǎn)單地設(shè)置一個(gè)標(biāo)志位,名稱就叫做isCancelled。啟動(dòng)線程后,定期檢查這個(gè)標(biāo)志位。如果isCancelled=true,那么線程就馬上結(jié)束。

public class MyThread implements Runnable{
private volatile boolean isCancelled;
public void run(){
while(!isCancelled){
//do something
}
}
public void cancel(){ isCancelled=true; }
}

注意的是,isCancelled需要為volatile,保證線程讀取時(shí)isCancelled是最新數(shù)據(jù)。
我以前經(jīng)常用這種簡(jiǎn)單方法,在大多時(shí)候也很有效,但并不完善??紤]下,如果線程執(zhí)行的方法被阻塞,那么如何執(zhí)行isCancelled的檢查呢?線程有可能永遠(yuǎn)不會(huì)去檢查標(biāo)志位,也就卡住了。

使用中斷

Java提供了中斷機(jī)制,Thread類下有三個(gè)重要方法。

  • public void interrupt()
  • public boolean isInterrupted()
  • public static boolean interrupted(); // 清除中斷標(biāo)志,并返回原狀態(tài)

每個(gè)線程都有個(gè)boolean類型的中斷狀態(tài)。當(dāng)使用Thread的interrupt()方法時(shí),線程的中斷狀態(tài)會(huì)被設(shè)置為true。
下面的例子啟動(dòng)了一個(gè)線程,循環(huán)執(zhí)行打印一些信息。使用isInterrupted()方法判斷線程是否被中斷,如果是就結(jié)束線程。

public class InterruptedExample {
public static void main(String[] args) throws Exception {
InterruptedExample interruptedExample = new InterruptedExample();
interruptedExample.start();
}
public void start() {
MyThread myThread = new MyThread();
myThread.start();
try {
Thread.sleep(3000);
myThread.cancel();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class MyThread extends Thread{
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("test");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("interrupt");
//拋出InterruptedException后中斷標(biāo)志被清除,標(biāo)準(zhǔn)做法是再次調(diào)用interrupt恢復(fù)中斷
Thread.currentThread().interrupt();
}
}
System.out.println("stop");
}
public void cancel(){
interrupt();
}
}
}

對(duì)線程調(diào)用interrupt()方法,不會(huì)真正中斷正在運(yùn)行的線程,只是發(fā)出一個(gè)請(qǐng)求,由線程在合適時(shí)候結(jié)束自己。

例如Thread.sleep這個(gè)阻塞方法,接收到中斷請(qǐng)求,會(huì)拋出InterruptedException,讓上層代碼處理。這個(gè)時(shí)候,你可以什么都不做,但等于吞掉了中斷。因?yàn)閽伋鯥nterruptedException后,中斷標(biāo)記會(huì)被重新設(shè)置為false!看sleep()的注釋,也強(qiáng)調(diào)了這點(diǎn)。

@throws InterruptedException
if any thread has interrupted the current thread. 
The interrupted status of the current thread is 
cleared when this exception is thrown.
public static native void sleep(long millis) throws InterruptedException;

記得這個(gè)規(guī)則:什么時(shí)候都不應(yīng)該吞掉中斷!每個(gè)線程都應(yīng)該有合適的方法響應(yīng)中斷!

所以在InterruptedExample例子里,在接收到中斷請(qǐng)求時(shí),標(biāo)準(zhǔn)做法是執(zhí)行Thread.currentThread().interrupt()恢復(fù)中斷,讓線程退出。

從另一方面談起,你不能吞掉中斷,也不能中斷你不熟悉的線程。如果線程沒(méi)有響應(yīng)中斷的方法,你無(wú)論調(diào)用多少次interrupt()方法,也像泥牛入海。

用Java庫(kù)的方法比自己寫(xiě)的要好

自己手動(dòng)調(diào)用interrupt()方法來(lái)中斷程序,OK。但是Java庫(kù)提供了一些類來(lái)實(shí)現(xiàn)中斷,更好更強(qiáng)大。

Executor框架提供了Java線程池的能力,ExecutorService擴(kuò)展了Executor,提供了管理線程生命周期的關(guān)鍵能力。其中,ExecutorService.submit返回了Future對(duì)象來(lái)描述一個(gè)線程任務(wù),它有一個(gè)cancel()方法。

下面的例子擴(kuò)展了上面的InterruptedExample,要求線程在限定時(shí)間內(nèi)得到結(jié)果,否則觸發(fā)超時(shí)停止。

public class InterruptByFuture {
public static void main(String[] args) throws Exception {
ExecutorService es = Executors.newSingleThreadExecutor();
Future<?> task = es.submit(new MyThread());
try {
//限定時(shí)間獲取結(jié)果
task.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
//超時(shí)觸發(fā)線程中止
System.out.println("thread over time");
} catch (ExecutionException e) {
throw e;
} finally {
boolean mayInterruptIfRunning = true;
task.cancel(mayInterruptIfRunning);
}
}
private static class MyThread extends Thread {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) { 
try {
System.out.println("count");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("interrupt");
Thread.currentThread().interrupt();
}
}
System.out.println("thread stop");
}
public void cancel() {
interrupt();
}
}
}

Future的get方法可以傳入時(shí)間,如果限定時(shí)間內(nèi)沒(méi)有得到結(jié)果,將會(huì)拋出TimeoutException。此時(shí),可以調(diào)用Future的cancel()方法,對(duì)任務(wù)所在線程發(fā)出中斷請(qǐng)求。
cancel()有個(gè)參數(shù)mayInterruptIfRunning,表示任務(wù)是否能夠接收到中斷。

  • mayInterruptIfRunning=true時(shí),任務(wù)如果在某個(gè)線程中運(yùn)行,那么這個(gè)線程能夠被中斷;
  • mayInterruptIfRunning=false時(shí),任務(wù)如果還未啟動(dòng),就不要運(yùn)行它,應(yīng)用于不處理中斷的任務(wù)

要注意,mayInterruptIfRunning=true表示線程能接收中斷,但線程是否實(shí)現(xiàn)了中斷不得而知。線程要正確響應(yīng)中斷,才能真正被cancel。

線程池的shutdownNow()會(huì)嘗試停止池內(nèi)所有在執(zhí)行的線程,原理也是發(fā)出中斷請(qǐng)求。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 如何使用hutool做本地緩存的工具類

    如何使用hutool做本地緩存的工具類

    這篇文章主要介紹了如何使用hutool做本地緩存的工具類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • idea配置檢查XML中SQL語(yǔ)法及書(shū)寫(xiě)sql語(yǔ)句智能提示的方法

    idea配置檢查XML中SQL語(yǔ)法及書(shū)寫(xiě)sql語(yǔ)句智能提示的方法

    idea連接了數(shù)據(jù)庫(kù),也可以執(zhí)行SQL查到數(shù)據(jù),但是無(wú)法識(shí)別sql語(yǔ)句中的表導(dǎo)致沒(méi)有提示,下面這篇文章主要給大家介紹了關(guān)于idea配置檢查XML中SQL語(yǔ)法及書(shū)寫(xiě)sql語(yǔ)句智能提示的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • Spring Cloud實(shí)現(xiàn)5分鐘級(jí)區(qū)域切換的操作方法

    Spring Cloud實(shí)現(xiàn)5分鐘級(jí)區(qū)域切換的操作方法

    Spring Cloud 2023.x通過(guò)智能路由預(yù)熱、多活數(shù)據(jù)同步和自動(dòng)化流量切換,實(shí)現(xiàn)5分鐘內(nèi)完成跨區(qū)域故障轉(zhuǎn)移,本文以某電商平臺(tái)從AWS亞太切換至阿里云華東的實(shí)戰(zhàn)為例,詳解關(guān)鍵技術(shù)路徑,需要的朋友可以參考下
    2025-04-04
  • jquery uploadify和apache Fileupload實(shí)現(xiàn)異步上傳文件示例

    jquery uploadify和apache Fileupload實(shí)現(xiàn)異步上傳文件示例

    這篇文章主要介紹了jquery uploadify和apache Fileupload實(shí)現(xiàn)異步上傳文件示例,需要的朋友可以參考下
    2014-05-05
  • 在Java中使用日志框架log4j的方法

    在Java中使用日志框架log4j的方法

    Log4j有三個(gè)主要的組件/對(duì)象:Loggers(記錄器),Appenders (輸出源)和Layouts(布局)。這里可簡(jiǎn)單理解為日志類別,日志要輸出的地方和日志以何種形式輸出,今天通過(guò)本文給大家分享Java日志框架log4j的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-08-08
  • Java之OutputStreamWriter流案例詳解

    Java之OutputStreamWriter流案例詳解

    這篇文章主要介紹了Java之OutputStreamWriter流案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java中注解@JsonFormat與@DateTimeFormat的使用

    Java中注解@JsonFormat與@DateTimeFormat的使用

    從數(shù)據(jù)庫(kù)獲取時(shí)間傳到前端進(jìn)行展示的時(shí)候,我們有時(shí)候可能無(wú)法得到一個(gè)滿意的時(shí)間格式的時(shí)間日期,本文主要介紹了Java中注解@JsonFormat與@DateTimeFormat的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • Java Spring事務(wù)的隔離級(jí)別詳解

    Java Spring事務(wù)的隔離級(jí)別詳解

    這篇文章主要介紹了Java Spring事務(wù)的隔離級(jí)別,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • Java處理Webp圖片格式轉(zhuǎn)換的示例代碼

    Java處理Webp圖片格式轉(zhuǎn)換的示例代碼

    這篇文章主要介紹了Java處理Webp圖片格式轉(zhuǎn)換的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • SpringBoot如何集成PageHelper分頁(yè)功能

    SpringBoot如何集成PageHelper分頁(yè)功能

    這篇文章主要介紹了SpringBoot如何集成PageHelper分頁(yè)功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03

最新評(píng)論

长白| 屏边| 金塔县| 太谷县| 宜黄县| 囊谦县| 武山县| 舒城县| 凤山县| 浑源县| 台湾省| 新蔡县| 凤山县| 大竹县| 全椒县| 舒城县| 兰溪市| 德州市| 陆良县| 淳化县| 六安市| 营口市| 卓资县| 玉门市| 印江| 浑源县| 肇东市| 论坛| 工布江达县| 瓮安县| 洛阳市| 兴义市| 禹城市| 仙游县| 玉环县| 方城县| 中牟县| 汉沽区| 宝清县| 都匀市| 桦甸市|