日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1、為什么廢棄Thread的stop函數(shù)?

對于有多線程開發(fā)經(jīng)驗(yàn)的開發(fā)者,應(yīng)該大多數(shù)在開發(fā)過程中都遇到過這樣的需求,就是在某種情況下,希望立即停止一個線程。

比如:做Android App開發(fā),當(dāng)打開一個界面時,需要開啟線程請求網(wǎng)絡(luò)獲取界面的數(shù)據(jù),但有時候由于網(wǎng)絡(luò)特別慢,用戶沒有耐心等待數(shù)據(jù)獲取完成就將界面關(guān)閉,此時就應(yīng)該立即停止線程任務(wù),不然一般會內(nèi)存泄露,造成系統(tǒng)資源浪費(fèi),如果用戶不斷地打開又關(guān)閉界面,內(nèi)存泄露會累積,最終導(dǎo)致內(nèi)存溢出,APP閃退。

可能有不少開發(fā)者用過Thread的stop去停止線程,當(dāng)然此函數(shù)確實(shí)能停止線程,不過JAVA官方早已將它廢棄,不推薦使用,這是為什么?

  1. stop是通過立即拋出ThreadDeath異常,來達(dá)到停止線程的目的,此異常拋出有可能發(fā)生在任何一時間點(diǎn),包括在catch、finally等語句塊中,但是此異常并不會引起程序退出(筆者只測試了Java8)。
  2. 由于有異常拋出,導(dǎo)致線程會釋放全部所持有的鎖,極可能引起線程安全問題。

由于以上2點(diǎn),stop這種方式停止線程是不安全的。

下面是stop的源碼(Java8):

 @Deprecated
 public final void stop() {
 SecurityManager security = System.getSecurityManager();
 if (security != null) {
 checkAccess();
 if (this != Thread.currentThread()) {
 security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
 }
 }
 // A zero status value corresponds to "NEW", it can't change to
 // not-NEW because we hold the lock.
 if (threadStatus != 0) {
 resume(); // Wake up thread if it was suspended; no-op otherwise
 }
 // The VM can handle all thread states
 stop0(new ThreadDeath());
 }
 
 private native void stop0(Object o);

上述源碼中關(guān)鍵代碼就是stop0(new ThreadDeath())函數(shù),這是Native函數(shù),傳遞的參數(shù)是ThreadDeath,ThreadDeath是一個異常對象,該對象從Native層拋到了Java層,從而導(dǎo)致線程停止,不過此異常并不會引起程序退出。

很多時候?yàn)榱吮WC數(shù)據(jù)安全,線程中會編寫同步代碼,如果當(dāng)線程正在執(zhí)行同步代碼時,此時調(diào)用stop,引起拋出異常,導(dǎo)致線程持有的鎖會全部釋放,此時就不能確保數(shù)據(jù)的安全性,出現(xiàn)無法預(yù)期的錯亂數(shù)據(jù),還有可能導(dǎo)致存在需要被釋放的資源得不到釋放,引發(fā)內(nèi)存泄露。所以用stop停止線程是不推薦的。

2、用Thread的interrupt結(jié)束線程

其實(shí)調(diào)用Thread對象的interrupt函數(shù)并不是立即中斷線程,只是將線程中斷狀態(tài)標(biāo)志設(shè)置為true,當(dāng)線程運(yùn)行中有調(diào)用其阻塞的函數(shù)(Thread.sleep,Object.wait,Thread.join等)時,阻塞函數(shù)調(diào)用之后,會不斷地輪詢檢測中斷狀態(tài)標(biāo)志是否為true,如果為true,則停止阻塞并拋出InterruptedException異常,同時還會重置中斷狀態(tài)標(biāo)志;如果為false,則繼續(xù)阻塞,直到阻塞正常結(jié)束。

因此,可以利用這種中斷機(jī)制來控制結(jié)束線程的運(yùn)行。只要理解機(jī)制,代碼的實(shí)現(xiàn)其實(shí)比較簡單。

2.1、結(jié)束未使用阻塞函數(shù)的線程

public class Main {
 public static void main(String[] args) {
 InnerClass innerClass = new InnerClass();
 Thread thread = new Thread(innerClass);
 thread.start();
 long i = System.currentTimeMillis();
 while (System.currentTimeMillis() - i < 10 * 1000) {
 thread.isAlive();
 }
 thread.interrupt();
 }
 static class InnerClass implements Runnable {
 @Override
 public void run() {
 System.err.println("start work");
 while (!Thread.currentThread().isInterrupted()) {
 System.out.println("doing work");
 }
 System.err.println("done work");
 }
 }
}

思路其實(shí)就是用isInterrupted來判斷線程是否處于中斷狀態(tài),若是中斷狀態(tài),則跳出正在執(zhí)行的任務(wù),使線程結(jié)束運(yùn)行。

2.2、結(jié)束使用阻塞函數(shù)的線程

public class Main {
 public static void main(String[] args) {
 InnerClass innerClass = new InnerClass();
 Thread thread = new Thread(innerClass);
 thread.start();
 long i = System.currentTimeMillis();
 while (System.currentTimeMillis() - i < 10 * 1000) {
 thread.isAlive();
 }
 thread.interrupt();
 }
 static class InnerClass implements Runnable {
 @Override
 public void run() {
 System.err.println("start work");
 while (!Thread.currentThread().isInterrupted()) {
 System.out.println("doing work");
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 Thread.currentThread().interrupt();
 }
 }
 System.err.println("done work");
 }
 }
}

思路同2.1,需要注意的是,調(diào)用sleep函數(shù)觸發(fā)InterruptedException異常時,在catch代碼塊中需調(diào)用interrupt函數(shù),使線程再次處于中斷狀態(tài),使while循環(huán)條件為false,使線程跳出循環(huán),結(jié)束運(yùn)行。若不調(diào)用,while循環(huán)為死循環(huán),線程無法結(jié)束。

2.3、關(guān)于Thread的靜態(tài)函數(shù)interrupted與Thread的對象函數(shù)isInterrupted

先對比下2函數(shù)的源碼:

 public static boolean interrupted() {
 return currentThread().isInterrupted(true);
 }
 public boolean isInterrupted() {
 return isInterrupted(false);
 }
 /**
 * Tests if some Thread has been interrupted. The interrupted state
 * is reset or not based on the value of ClearInterrupted that is
 * passed.
 */
 private native boolean isInterrupted(boolean ClearInterrupted);

從源碼中可以看出,2函數(shù)都是調(diào)用了Native函數(shù)private native boolean isInterrupted(boolean ClearInterrupted);,前者調(diào)用傳的參數(shù)為true,所以,調(diào)用interrupted函數(shù),會在檢測線程中斷狀態(tài)標(biāo)志是否為true后,還會將中斷狀態(tài)標(biāo)志重置為false。而isInterrupted函數(shù)只是檢測線程中斷狀態(tài)標(biāo)志。

分享到:
標(biāo)簽:線程 中斷 Java
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定