Java學習 -- 線程(2)

Thread的常用方法

  • public final void setName(String name)
    設置當前線程的名字
  • public static Thread currentThread()
    返回對當前正在執行的線程對象的引用
  • public final String getName()
    返回當前線程的名字
// 線程方法的介紹
class A extends Thread {
	public void run() {
		System.out.println("AAAA");
		System.out.printf("%s在執行!\n", Thread.currentThread().getName());// Thread-0在執行!
	}
}

public class TestThread {
	public static void main(String[] args) {
		A aa = new A();
		aa.start()

		System.out.println("BBBB");
		System.out.printf("%s在執行!\n", Thread.currentThread().getName()); // main在執行
	}
}

線程的控制

  • 線程控制的基本方法
    在這裏插入圖片描述
方法 功能
isAlive() 判斷線程是否還“活”着,即線程是否還未終止
getPriority 獲得線程的優先級數值
setPriority() 設置線程的優先級數值
Thread.sleep() 將當前線程睡眠指定毫秒數
jion() 當用某線程的該方法,將當前線程與該線程“合併”,即等待該線程結束,再恢復當前線程的運行
yield() 讓出CPU,當前線程進入就緒隊列等待調度
wait() 當前線程進入對象的wait pool
notify() / notifyAll() 喚醒對象的wait pool中的一個 / 所有等待線程

線程優先級

線程的優先級用數字來表示,範圍從1到10。
主線程的缺省優先級是5,子線程的優先級默認與其父線程相同。

  • Java提供一個線程調度器來監控程序中啓動後進入就緒狀態的所有線程。線程調度器按照線程的優先級決定應調度哪個線程來執行。
  • 線程的優先級用數字來表示,範圍從1到10,一個線程的缺省優先級是5.
    Thread.MIN_PRIORITY = 1
    Thread.MAX_PRIORITY = 10
    Thread.NORM_PRIORITY = 5
  • 使用下述線程方法獲得或設置線程對象的優先級
    int getPriority()
    void setPriority(int newPriority)
    通常高優先級的線程將先於優先級低的線程執行,但並不總是這樣的,因此實際開發並不單純依賴優先級來決定線程運行次序。
class T1 implements Runnable {
	public void run() {
		for (int i=0; i<100; ++i)
			System.out.println("T1: " + i);
	}
}
class T2 implements Runnable {
	public void run() {
		for (int i=0; i<100; ++i)
			System.out.println("------T2: " + i);
	}
}
public class TestPriority {
	public static void main(String[] args) {
		Thread t1 = new Thread(new T1());
		Thread t2 = new Thread(new T2());
		t1.setPriority(Thread.NORM_PRIORITY + 3);// t1 的優先級被設爲8,比t2優先級5要大,所以線程t1先執行,執行完再執行t2進程
		t1.start();
		t2.start();
	}
}

線程的休眠

  • 線程休眠-----暫停執行當前運行中的線程,使之進入阻塞狀態,待經過指定的“延遲時間”後再醒來並轉入到就緒狀態。
  • Thread類提供的相關方法:
    public static void sleep(long millis)
    public static void sleep(long millis, int nanos)
  • 由於是靜態方法,可以由Thread直接調用
  • sleep()方法會拋出InterruptedException異常,我們必須得對其進行捕捉
class A implements Runnable {
	public void run() { // 2行
		for (int i=0; i<10; ++i) {
			System.out.println(Thread.currentThread().getName() + " " + i);
			try {
				Thread.sleep(1000); // 這裏的Thread.sleep(1000)會拋出異常
				// 所以必須得進行捕捉,不能在2行的後面添加throws Exception
			} catch (Exception e) {
			}
		}
	}
}

public class TeatSleep {
	public static void main(String[] args) {
		A aa = new A();
		Thread tt = new Thread(aa);
		tt.start();
	}
}

無論是繼承Thread類的run方法還是實現了Runnable接口的run方法,都不能拋出任何異常

class A implements Runnable {
	public void run() // throws Exception { // 註釋符不能去掉,否則編譯會報錯
	}
}
class B extends Thread {
	public void run() // throws Exception { // 註釋符不能去掉,否則編譯會報錯
	}
}

原因:重寫方法拋出異常的範圍不能大於被重寫方法排除的異常範圍

線程的讓步

  • 讓出CPU,給其他線程執行的機會
  • 讓運行中的線程主動放棄當前獲得的CPU處理機會,但不是使該線程阻塞,而是使之轉入就緒狀態。
    public static void yield()
class MyThread implements Runnable {
	public void run() {
		for (int i=1; i<=100; ++i) {
			System.out.println(Thread.currentThread().getName() + ":" + i);
			if (0 == i%10)
				Thread.yield();
		}
	}
}
public class TestYield {
	public static void main(String[] args) {
		MyThread mt = new MyThread();
		Thread t1 = new Thread(mt);
		Thread t2 = new Thread(mt);

		t1.setName("線程A");
		t2.setName("線程B");

		t1.start();
		t2.start();
	}
}

線程的串行化

  • 在多線程程序中,如果在一個線程運行的過程中要用到另一個線程的運行結果,則可進行線程的串行化處理
    public final void jion() throws InterruptedException
class MyRunner implements Runnable {
	public void run() {
		for (int i=0; i<50; i++) 
			System.out.println("子線程:" + i);
	}
}
public class TestJoin {
	public static void main(String[] args) {
		MyRunner r = new MyRunner();
		Thread t = new Thread(r);
		t.start();
		try {
			t.jion(); // 7行
		} catch(InterruptedException e ) {
			e.printStackTrace();
		}
		for (int i=0; i<50; i++)
			System.out.println("主線程:" + i);
	}
}

7行的 t.jion()暫停當前正在執行t.jion()的線程,直到t所對應的線程運行終止之後,當前線程纔會獲得繼續執行的機會
注意:t.jion()不是暫停t對象所對應的線程

線程的掛起和恢復

  • 線程掛起----暫時停止當前運行中的線程,使之轉入阻塞狀態,並且不會自動恢復運行。
  • 線程恢復----- 使得一個已掛起的線程恢復運行。
  • Thread類提供的相關方法
    public final void suspend()
    public final void resume()
  • suspend()方法掛起線程時並不釋放其鎖定的資源,這可能會影響其他線程的運行,且容易導致線程的死鎖,已經不提倡使用

生命週期控制

  • 如何結束一個線程
class A implements Runnable {
	private boolean flag = true;
	public void run() {
		while (flag) 
			System.out.println("AAAA");
	}
	public void shutDown() {
		this.flag = false;
	}
}
public class TestShutThread {
	public static void main(String[] args) {
		A aa = new A();
		Thread tt = new Thread(aa);
		tt.start();
		try {
			Thread.sleep(5000);
		} catch (Exception e) {
			e.printStackTrace();
		}
		aa.shutDown();
	}
}
發佈了74 篇原創文章 · 獲贊 14 · 訪問量 8783
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章