Java多執行緒-執行緒中止

小碼農薛堯發表於2019-08-26

不正確的執行緒中止-Stop

Stop:中止執行緒,並且清除監控器鎖的資訊,但是可能導致 執行緒安全問題,JDK不建議用。 Destroy: JDK未實現該方法。

/**
 * @author simon
 */
public class StopThread extends Thread {
    private int i = 0, j = 0;
    @Override
    public void run() {
        synchronized (this) {
            // 增加同步鎖,確保執行緒安全
            ++i;
            try {
                // 休眠10秒,模擬耗時操作
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ++j;
        }
    }
    /** * 列印i和j */
    public void print() {
        System.out.println("i=" + i + " j=" + j);
    }
}
複製程式碼
/**
 * @author simon
 * 示例3 - 執行緒stop強制性中止,破壞執行緒安全的示例
 */
public class Demo {
    public static void main(String[] args) throws InterruptedException {
        StopThread thread = new StopThread();
        thread.start();
        // 休眠1秒,確保i變數自增成功
        Thread.sleep(1000);
        // 暫停執行緒
        thread.stop(); // 錯誤的終止
        //thread.interrupt(); // @正確終止
        while (thread.isAlive()) {
            // 確保執行緒已經終止
        } // 輸出結果
        thread.print();
    }
}
複製程式碼

理想狀態:要麼自增成功i=1, j=1,要麼自增失敗i=0, j=0 真正程式執行結果:i=1, j=0

Java多執行緒-執行緒中止

沒有保證同步程式碼塊裡面資料的一致性,破壞了執行緒安全 stop方法直接停止執行緒

正確的執行緒中止-interrupt

如果目標執行緒在呼叫Object class的wait()、wait(long)或wait(long, int)方法、join()、join(long, int)或sleep(long, int)方法時被阻塞,那麼Interrupt會生效,該執行緒的中斷狀態將被清除,丟擲InterruptedException異常。

如果目標執行緒是被I/O或者NIO中的Channel所阻塞,同樣,I/O操作會被中斷或者返回特殊異常值。達到終止執行緒的目的。

如果以上條件都不滿足,則會設定此執行緒的中斷狀態。

對Demo中的示例,stop()改成interrupt()後,最終輸出為"i=1 j=1",資料一致。

Java多執行緒-執行緒中止

正確的執行緒中止-標誌位

/** 通過狀態位來判斷 */
public class Demo4 extends Thread {
  public volatile static boolean flag = true;

  public static void main(String[] args) throws InterruptedException {
    new Thread(() -> {
      try {
        while (flag) { // 判斷是否執行
          System.out.println("程式執行中");
          Thread.sleep(1000L);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }).start();
    // 3秒之後,將狀態標誌改為False,代表不繼續執行
    Thread.sleep(3000L);
    flag = false;
    System.out.println("程式執行結束");
  }
}
複製程式碼

在上方程式碼邏輯中,增加一個判斷,用來控制執行緒執行的中止。

Java多執行緒-執行緒中止

相關文章