1. 程式人生 > >多執行緒(1)-執行緒的終止方法

多執行緒(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();
		}
		
	}
}

執行後得結果: