Java多線程與併發學習之(四):線程常用方法

java線程對象有一些經常使用的方法,如:

(1).currentThread():返回代碼段正在被哪個線程調用。

(2).isAlive():判斷當前線程是否處於活動狀態。

(3).getId():返回線程唯一標示。

(4).interrupt():中斷線程。

(5).interrupted():判斷當前線程是否已經中斷。

(6).isInterrupt():判斷線程是否已經中斷。

(7).stop():將線程強制停止。

(8).suspend():暫停線程。

(9).resume():恢復線程執行。

(10).yield():放棄當前的CPU資源,將它讓給其他任務去佔用CPU執行時間。


下面逐一舉例說明各方法作用。

(1).currentThread():返回代碼段正在被哪個線程調用

public class Run1 {
	public static void main(String[] args) {
		System.out.println("當前線程名稱:" + Thread.currentThread().getName());
	}
}
輸出爲:“當前線程名稱:main”,說明main方法被名爲main的線程調用。
public class MyThread1 extends Thread{
	public MyThread1(){
		System.out.println("構造方法的打印:" + Thread.currentThread().getName());
	}
	@Override
	public void run(){
		System.out.println("run方法的打印:" + Thread.currentThread().getName());
	}
}
 public class Run1 {
	public static void main(String[] args) {
		MyThread1 thread = new MyThread1();
		thread.start();
		//thread.run();
	}
}

當執行thread.start();方法和thread.run();方法打印結果分別爲:




    打印結果不同的原因在於調用start()方法時,啓動了新的線程,run方法是被新線程來執行的,構造方法兩種情況都是被main線程執行,直接調用run方法時,並未啓動新線程,直接通過main線程執行的run方法,所以兩次打印結果不同。

    很多時候Thread.currentThread().getName()會與this.getName()方法進行比較,其實比較的是currentThread和this獲取到線程這兩種方式的區別。

a.Thread.currentThread()在兩種實現線程的方式(實現Runnable接口和繼承Thread類)中都可以使用;this方式只能在繼承方式中使用;

b.currentThread()方法返回的是對當前正在執行的線程的引用,this代表的是當前調用它所在函數所屬的對象的引用。


(2).isAlive():判斷當前線程是否處於活動狀態。

public class Run1 {
	public static void main(String[] args) {
		MyThread2 thread = new MyThread2();
		System.out.println("begin = " + thread.isAlive());
		thread.start();
		System.out.println("end = " + thread.isAlive());
	}
}

    什麼是活動狀態呢,活動狀態就是線程已經啓動且尚未終止。線程處於正在運行或準備開始運行的狀態,就認爲線程是“存活”的。

    其實上面的結果中end後的狀態是不確定的,有可能是true也可能是false,看main線程執行end這行時,thread線程是否已經執行完畢了,這個地方打印的是true是因爲thread線程還未執行完畢。


(3).getId():返回線程唯一標示。

public class Run1 {
	public static void main(String[] args) {
		MyThread2 thread = new MyThread2();
		System.out.println(thread.getName() + "  " + thread.getId());
	}
}
輸出爲:Thread-0  10


(4).interrupt():中斷線程。

(5).interrupted():判斷當前線程是否已經中斷。

(6).isInterrupt():判斷線程是否已經中斷。

(7).stop():將線程強制停止。

    這幾個方法一起說,因爲這三個方法都是跟停止線程或判斷線程中斷狀態相關。java中有三種方法可以終止正在運行的線程:

a.使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止;

b.使用stop方法強行終止線程,但是不推薦使用這個方法,因爲stop和suspend(暫停線程)及resume(恢復線程執行)一樣,都是作廢過期方法,使用它們可能產生不可預料的結果;

c.使用interrupt方法中斷線程。


    interrupt():線程的thread.interrupt()方法是中斷線程,將會設置該線程的中斷狀態位,即設置爲true,中斷的結果線程是死亡、還是等待新的任務或是繼續運行至下一步,就取決於這個程序本身。線程會不時地檢測這個中斷標示位,以判斷線程是否應該被中斷(中斷標示值是否爲true)。它並不像stop方法那樣會中斷一個正在運行的線程。如果線程在調用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法,或者該類的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法過程中受阻,則其中斷狀態將被清除,它還將收到一個 InterruptedException。也就是說,interrupt()方法並不會真正中斷一個線程,只是會設置線程的中斷狀態爲true,當線程調用wait()、wait(long)這些方法產生阻塞時,會來判斷線程的狀態是否是中斷,如果是,會拋出InterruptedException異常的方式中斷線程。

public class MyThread2 extends Thread{
	@Override
	public void run(){
		super.run();
		for (int i = 1; i <= 500000; i++) {
			System.out.println("i=" + i);
		}
	}
}
public class Run1 {
	public static void main(String[] args) {
		try {
		MyThread2 thread = new MyThread2();
		thread.start();
		Thread.sleep(1000);
		thread.interrupt();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
	}
}

   interrupted():測試當前線程是否已經中斷,並且具有清除狀態標誌爲false的作用。換句話說,如果連續兩次調用該方法,則第二次調用將返回false(在第一次調用已經清除了其中中斷狀態之後,且第二次調用檢驗中斷狀態前,當前線程再次中斷的情況除外)。

public class Run1 {
	public static void main(String[] args) {
		try {
			MyThread2 thread = new MyThread2();
			thread.start();
			Thread.sleep(50);
			thread.interrupt();
			System.out.println("是否停止1? = " + thread.interrupted());
			System.out.println("是否停止2? = " + thread.interrupted());
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
		System.out.println("end!");
	}
}

    樣例中雖然是在thread對象上調用的interrupt()方法來中斷thread對象所代表的線程,在後面使用interrupted()方法來判斷thread對象所代表的線程是否中斷,但從輸出來看,線程並未停止,這也說明了interrupted()方法的解釋:測試當前線程是否已經中斷。這個“當前線程”是main線程,它從未中斷過,所以打印了兩個false。

public class Run1 {
	public static void main(String[] args) {
		Thread.currentThread().interrupt();
		System.out.println("是否停止1? = " + Thread.interrupted());
		System.out.println("是否停止2? = " + Thread.interrupted());
		System.out.println("end!");
	}
}

    此時main線程產生了中斷的效果。


   isInterrupt():測試線程Thread對象是否已經是中斷狀態,但不清除狀態標誌

public static void main(String[] args) {
		try {
			MyThread2 thread = new MyThread2();
			thread.start();
			Thread.sleep(50);
			thread.interrupt();
			System.out.println("是否停止1? = " + thread.isInterrupted());
			System.out.println("是否停止2? = " + thread.isInterrupted());
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
		System.out.println("end!");
	}


   stop():暴力終止線程。

public class MyThread3 extends Thread{
	@Override
	public void run(){
		super.run();
		for (int i = 1; i <= 10000; i++) {
			System.out.println("i=" + i);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
public static void main(String[] args) {
		try {
			MyThread3 thread = new MyThread3();
			thread.start();
			Thread.sleep(5000);
			thread.stop();
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
	}

   

    (8).suspend():暫停線程。

    (9).resume():恢復線程執行。

public class MyThread4 extends Thread{
	private long i = 0;
	
	public long getI() {
		return i;
	}
	public void setI(long i) {
		this.i = i;
	}

	@Override
	public void run(){
		super.run();
		while(true){
			i++;
		}
	}
}
public static void main(String[] args) {
		try {
			MyThread4 thread = new MyThread4();
			thread.start();
			Thread.sleep(5000);
			
			thread.suspend();
			System.out.println("A= " + System.currentTimeMillis() + "  i=" + thread.getI());
			Thread.sleep(5000);
			System.out.println("A= " + System.currentTimeMillis() + "  i=" + thread.getI());
			
			thread.resume();
			Thread.sleep(5000);
			
			thread.suspend();
			System.out.println("B= " + System.currentTimeMillis() + "  i=" + thread.getI());
			Thread.sleep(5000);
			System.out.println("B= " + System.currentTimeMillis() + "  i=" + thread.getI());
			
		} catch (InterruptedException e) {
			System.out.println("main catch");
			e.printStackTrace();
		}
	}

    suspend()方法和resume()方法是廢棄方法,也不提倡使用,有獨佔和不同步的缺點。如果使用不當,極易造成公共的同步對象的獨佔,使得其他線程無法訪問公共同步對象。


    (10).yield():放棄當前的CPU資源,將它讓給其他任務去佔用CPU執行時間。但放棄的時間不確定,有可能剛剛放棄,馬上又獲得CPU的時間片。

public class MyThread5 extends Thread{
	@Override
	public void run(){
		long beginTime = System.currentTimeMillis();
		long count = 0;
		for (int i = 0; i < 50000000; i++) {
			//Thread.yield();
			count = count + i;
		}
		long endTime = System.currentTimeMillis();
		System.out.println("計算結果count=" + count + ",用時:" + (endTime-beginTime) + "ms");
	}
}
public static void main(String[] args) {
	MyThread5 thread = new MyThread5();
	thread.start();
}
註釋Thread.yield();這行時執行結果,很快;


不註釋Thread.yield();這行時執行結果,讓出CPU時間片時,相對來說要慢很多。









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章