多執行緒(1)-執行緒的終止方法
前言
近期看了一本關於多執行緒的書籍《Java多執行緒程式設計核心技術》。下面對學習到的關於執行緒的終止方法進行總結,如果有錯誤歡迎大家指出,如果對大家有幫助,歡迎轉載和點贊。
概述
java中有三中方法終止正在執行的執行緒:
(1)、通過推退出標誌,使執行緒正常退出,也就是當run方法完成後終止。
(2)、通過Thead.stop()方法強行終止執行緒,但是不推薦這麼使用,因為此方法是不安全的,已經作廢過期。
(3)、呼叫interrupt方法終止執行緒。
stop方法終止執行緒
呼叫stop方法後會馬上終止正在執行的執行緒,這樣強制終止執行緒,有可能會導致有些清理工作得不到完成,還有種情況是對鎖定的資料進行了解鎖,導致資料得不到同步處理,導致資料出現不一致。
下面以一個例子進行介紹。
package thread.stop; /*** * 用於執行緒stop方法中斷流程例子演示 * @author swh * */ public class ThreadStopTest extends Thread { public void run() { int i = 0; try { while( true ) { i++; System.out.println(i); Thread.sleep(1000L); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String args[]) { try { ThreadStopTest thread = new ThreadStopTest(); thread.start(); Thread.sleep(5000L); thread.stop(); } catch (InterruptedException e) { e.printStackTrace(); } } }
上面的程式碼比較簡單,及時在main 執行緒中啟動一個ThreadStopTest執行緒,然後休眠5秒,ThreadStopTest執行緒就是迴圈輸出i,輸出一次後休眠一秒,當ThreadStopTest迴圈執行5次main執行緒醒來,通過stop方法強制中斷執行緒。下面是執行的結果。
現在以一個簡單的例子來介紹下用stop方法中斷執行緒會導致的問題。
package thread.stop; /*** * 用於演示執行緒stop方法會導致的安全問題 * @author swh * */ public class SafeStopThread implements Runnable { private int i =0; @Override public void run() { synchronized("") { i++; try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } i--; System.out.println(Thread.currentThread().getName()+":"+i); } } public static void main(String args[]) { Thread thread=new Thread(new SafeStopThread()); thread.start(); for(int i =0;i<5;i++) { new Thread(thread).start(); } thread.stop(); } }
其中i是幾個執行緒公用的變數,其中run方法中加上了 synchronized 程式碼塊,表示內部是原子邏輯,它會先自增然後再自減少,按照synchronized同步程式碼塊的規 則來處理,此時無論啟動多少個執行緒,打印出來的結果都應該是a=0,但是如果有一個正在執 行的執行緒被stop,就會破壞這種原子邏輯。下面是執行的結果。
interrupt方法終止執行緒
interrupt方法並不像stop方法那樣強制中斷一個執行緒,而是給執行緒打上一個中斷標誌,並不是真的中斷執行緒。這裡先需要先介紹下兩個方法。
interrupted();測試當前執行緒是否已經中斷。此方法呼叫後會重置中斷標誌,即第一呼叫如果為true後會重置為false;
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
isinertrupted();測試執行緒是否已經中斷。
public boolean isInterrupted() {
return isInterrupted(false);
}
呼叫interrupt中斷執行緒例子如下,我們可以呼叫上面兩個方法來得到中斷標誌來判斷,來解決邏輯的原子性被破壞的問題;
package thread.interrupt;
/***
* 流程中斷
* @author swh
*
*/
public class InertruptThread extends Thread {
public void run() {
int i = 0;
try {
while(!this.isInterrupted()) {
i++;
System.out.println(i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
try {
InertruptThread inertruptThread = new InertruptThread();
inertruptThread.start();;
Thread.sleep(10L);
inertruptThread.interrupt();;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
執行後得結果: