摘要:文本將介紹兩種可以優(yōu)雅的終止線程的方式第一種在多線程模式中有一種叫兩步終止的模式可以優(yōu)雅的終止線程,這種模式采用了兩個(gè)步驟來終止線程,所以叫兩步終止模式。
第一種Java中原來在Thread中提供了stop()方法來終止線程,但這個(gè)方法是不安全的,所以一般不建議使用。文本將介紹兩種可以優(yōu)雅的終止線程的方式...
在JAVA《Java多線程模式》中有一種叫Two-Phase Termination(兩步終止)的模式可以優(yōu)雅的終止線程,這種模式采用了兩個(gè)步驟來終止線程,所以叫兩步終止模式。
先將執(zhí)行標(biāo)志位isShutdown 設(shè)為false,使工作中的線程轉(zhuǎn)變?yōu)?b>終止處理中的狀態(tài)
真正去執(zhí)行終止操作,這樣的做法可以保證線程的安全性、生命性和響應(yīng)性。
class Worker extends Thread { private volatile boolean isShutdown = true; public void shutdown() { System.out.println("接收到關(guān)閉通知......"); this.isShutdown = false; interrupt(); } @Override public void run() { while (this.isShutdown) { System.out.println("正在工作:" + System.currentTimeMillis()); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("打斷正在工作的線程......"); } } System.out.println("銷毀......"); } } public class ThreadClose { public static void main(String[] args) throws InterruptedException { Worker worker = new Worker(); worker.start();//開始工作 Thread.sleep(3 * 1000); worker.shutdown();//優(yōu)雅關(guān)閉 } }
運(yùn)行日志
正在工作:1505828036769 正在工作:1505828037770 正在工作:1505828038771 接收到關(guān)閉通知...... 打斷正在工作的線程...... 銷毀......
安全性:不會(huì)在線程正在執(zhí)行關(guān)鍵區(qū)域--Critical Section的時(shí)候突然結(jié)束掉
生命性:一定會(huì)進(jìn)行終止處理,shutdown()中,會(huì)調(diào)用interrupt(),保證即使線程處于sleep或wait狀態(tài)也可以被立即終止
響應(yīng)性:將isShutdown 設(shè)為volatile ,能保證線程收到終止請(qǐng)求后,會(huì)盡快開始終止處理。
存在的問題:針對(duì)沒有阻塞的情況:設(shè)置標(biāo)志變量,讓線程正常自然死亡,和諧!,但是如果在調(diào)用shutdown發(fā)生阻塞情況呢?
第二種在 《多線程第一章》的時(shí)候,介紹過守護(hù)線程的作用,那么是不是可以通過開啟守護(hù)線程的方式去監(jiān)聽
功能1.當(dāng)工作結(jié)束就關(guān)閉主線程(主線程銷毀守護(hù)線程也會(huì)跟著一同銷毀)
2.如果任務(wù)長(zhǎng)時(shí)間未完成,停止工作任務(wù),減少開銷
1.定義主線程與發(fā)送的指令
2.在主線程run方法中創(chuàng)建一個(gè)守護(hù)線程,用來執(zhí)行我們投遞的任務(wù)
3.前面已經(jīng)介紹過join的功能,它可以阻塞主線程,等待子線程完成后主線程繼續(xù)執(zhí)行
4.如果join釋放后,發(fā)送完成指令
private Thread executeService; private volatile boolean finished = false; public void execute(Runnable task) { executeService = new Thread(() -> { Thread runner = new Thread(task); runner.setDaemon(true); runner.start(); try { runner.join();//前面已經(jīng)說過join與線程了 finished = true; } catch (InterruptedException e) { System.out.println("打斷正在工作的線程......"); } }); executeService.start(); }
5.創(chuàng)建listener(long mills),監(jiān)聽工作情況
6.監(jiān)聽任務(wù)是否完成,如果未完成監(jiān)聽當(dāng)前是否逾期,逾期打斷線程結(jié)束監(jiān)聽
public void listener(long mills) { System.out.println("開啟監(jiān)聽......"); long currentTime = System.currentTimeMillis(); while (!finished) { if ((System.currentTimeMillis() - currentTime) >= mills) { System.out.println("工作耗時(shí)過長(zhǎng),開始打斷..."); executeService.interrupt();//打斷線程 break; } try { executeService.sleep(100L);//每隔100毫秒檢測(cè)一次 } catch (InterruptedException e) { e.printStackTrace(); } } }
7.測(cè)試
public static void main(String[] args) { WorkerService service = new WorkerService(); long start = System.currentTimeMillis(); service.execute(() -> { try { Thread.sleep(3 * 1000);// TODO 模擬加載數(shù)據(jù) } catch (InterruptedException e) { e.printStackTrace(); } }); service.listener(4 * 1000); System.out.println("一共耗時(shí):" + (System.currentTimeMillis() - start)); }
listener(4 * 1000) 的運(yùn)行日志,當(dāng)任務(wù)完成會(huì)直接退出,并不會(huì)一直占用
開啟監(jiān)聽...... 一共耗時(shí):3049
listener(2 * 1000) 的運(yùn)行日志,當(dāng)任務(wù)超時(shí)直接打斷線程,減少資源占用
開啟監(jiān)聽...... 工作耗時(shí)過長(zhǎng),開始打斷... 一共耗時(shí):2050 打斷正在工作的線程......- 說點(diǎn)什么
全文代碼:https://gitee.com/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter4
個(gè)人QQ:1837307557
battcn開源群(適合新手):391619659
微信公眾號(hào):battcn(歡迎調(diào)戲)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/67630.html
摘要:在退出時(shí)執(zhí)行必要的挽救措施。在這種情況下,一旦被提供,等待一個(gè)進(jìn)程終止指定的時(shí)間。如果進(jìn)程在該時(shí)間限制內(nèi)沒有終止,則通過發(fā)出或中的對(duì)等方強(qiáng)制終止進(jìn)程。所以有可能這是在中途執(zhí)行時(shí)發(fā)生的。 shutdownHook是一種特殊的結(jié)構(gòu),它允許開發(fā)人員插入JVM關(guān)閉時(shí)執(zhí)行的一段代碼。這種情況在我們需要做特殊清理操作的情況下很有用 用途 在Jboss,Jetty等容器中都可以看到shutdown...
摘要:并且,線程池在某些情況下還能動(dòng)態(tài)調(diào)整工作線程的數(shù)量,以平衡資源消耗和工作效率。同時(shí)線程池還提供了對(duì)池中工作線程進(jìn)行統(tǒng)一的管理的相關(guān)方法。 開發(fā)中經(jīng)常會(huì)遇到各種池(如:連接池,線程池),它們的作用就是為了提高性能及減少開銷,在JDK1.5以后的java.util.concurrent包中內(nèi)置了很多不同使用場(chǎng)景的線程池,為了更好的理解它們,自己手寫一個(gè)線程池,加深印象。 概述 1.什么是...
摘要:在之前,不能為線程單獨(dú)設(shè)置或指定一個(gè)默認(rèn)的,為了設(shè)置,需要繼承并覆寫方法。幸運(yùn)的是后線程提供了一個(gè)方法,用來捕獲并處理因線程中拋出的未知異常,以避免程序終止。 在單線程的開發(fā)過程中,通常采用try-catch的方式進(jìn)行異常捕獲,但是這種方式在多線程環(huán)境中會(huì)顯得無能為力,而且還有可能導(dǎo)致一些問題的出現(xiàn),比如發(fā)生異常的時(shí)候不能及時(shí)回收系統(tǒng)資源,或者無法及時(shí)關(guān)閉當(dāng)前的連接... 概述 Ja...
摘要:在前面的文章中介紹過觀察者模式及并發(fā)編程的基礎(chǔ)知識(shí),為了讓大家更好的了解觀察者模式故而特意寫了這篇番外概述在多線程下我們需要知道當(dāng)前執(zhí)行線程的狀態(tài)是什么比如運(yùn)行,關(guān)閉,異常等狀態(tài)的通知,而且不僅僅是更新當(dāng)前頁面。 在前面的文章中介紹過 觀察者模式 及 并發(fā)編程的基礎(chǔ)知識(shí),為了讓大家更好的了解觀察者模式故而特意寫了這篇番外.. 概述 在Java多線程下,我們需要知道當(dāng)前執(zhí)行線程的狀態(tài)是...
摘要:當(dāng)時(shí),會(huì)進(jìn)入循環(huán),系統(tǒng)會(huì)判斷主線程是否處于活躍狀態(tài),如果處于活躍狀態(tài),主線程就會(huì)不停的等待。 由于前段時(shí)間比較忙,線程這快學(xué)習(xí)停滯了,只能利用周日的時(shí)間來寫寫博客了,多線程Join方法的作用就是把指定的線程加入到當(dāng)前線程,讓主線程等待子線程結(jié)束之后才能繼續(xù)運(yùn)行,從而完成同步操作 介紹 join() 的作用:讓主線程等待子線程結(jié)束之后才能繼續(xù)運(yùn)行,首先先來看下以采集為案例的代碼,統(tǒng)計(jì)采...
閱讀 3217·2021-10-12 10:20
閱讀 2928·2021-09-27 13:56
閱讀 900·2021-09-27 13:36
閱讀 1503·2021-09-26 09:46
閱讀 2506·2019-08-30 14:02
閱讀 2754·2019-08-28 18:14
閱讀 1339·2019-08-26 10:32
閱讀 1782·2019-08-23 18:25