1. 程式人生 > >Java 執行緒第三版 第一章Thread導論、 第二章Thread的建立與管理讀書筆記

Java 執行緒第三版 第一章Thread導論、 第二章Thread的建立與管理讀書筆記

第一章 Thread導論

為何要用Thread ?

非阻塞I/O      I/O多路技術      輪詢(polling)      訊號 警告(Alarm)和定時器(Timer) 獨立的任務(Task) 並行演算法

第二章 Thread的建立與管理

一、什麼是Thread ?

    Thread是所在主機執行的應用程式任務(task)。 只有一個執行緒的例子:
public class Factorial {

		public static void main(String[] args) {
			int n = 5;
			System.out.print(n + "! is ");
			int fact = 1;
			while (n > 1) {
				fact *= n--;
			}
			System.out.println(fact);
		}
		
		// 程式碼的執行步驟是右上至下
		// Java的入口是Main方法
}


有兩個執行緒的例子,即兩個任務,應用程式會如何執行?依據所執行的應用程式的條件不同而有所不同。計算機反覆交替執行 為什麼不用多個應用程式來完成多個任務呢?因為Thread是在同一個應用程式中執行,他們共享在計算機上相同的記憶體空間,這樣可以緊密地共享資訊。 多工環境中的程序:
多執行緒環境中的執行緒    

二、建立Thread

執行緒建立有兩種方式,繼承自Thread 與 使用實現Runnable介面 Thread建構函式:
Thread() 
          分配新的 Thread 物件。 
Thread(Runnable target) 
          分配新的 Thread 物件。 
Thread(Runnable target, String name) 
          分配新的 Thread 物件。 
Thread(String name) 
          分配新的 Thread 物件。 
Thread(ThreadGroup group, Runnable target) 
          分配新的 Thread 物件。 
Thread(ThreadGroup group, Runnable target, String name) 
          分配新的 Thread 物件,以便將 target 作為其執行物件,將指定的 name 作為其名稱,並作為 group 所引用的執行緒組的一員。 
Thread(ThreadGroup group, Runnable target, String name, long stackSize) 
          分配新的 Thread 物件,以便將 target 作為其執行物件,將指定的 name 作為其名稱,作為 group 所引用的執行緒組的一員,並具有指定的堆疊大小。 
Thread(ThreadGroup group, String name) 
          分配新的 Thread 物件。



三、Thread的生命週期

1. 啟動Thread
class ThreadClass extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println("Helo World! " + i);
		}
	}
}

public class CreateThread {
	
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println("Helo World! " + i);
		}
	}
	
	public static void main(String[] args) {
		CreateThread ourClass = new CreateThread();
		ourClass.run();
		
		ThreadClass threadClass = new ThreadClass();
		threadClass.start();
	}
}


呼叫Thread子類的start方法都會執行run方法。 從log可以看出是在兩個執行緒中。但執行緒都是線性從前往後執行的。 public void run()
     如果該執行緒是使用獨立的 Runnable 執行物件構造的,則呼叫該 Runnable 物件的 run 方法;否則,該方法不執行任何操作並返回。
     Thread 的子類應該重寫該方法。 
public void start() 使該執行緒開始執行;Java 虛擬機器呼叫該執行緒的 run 方法。  結果是兩個執行緒併發地執行;當前執行緒(從呼叫返回給 start 方法)和另一個執行緒(執行其 run 方法)。  多次啟動一個執行緒是非法的。特別是當執行緒已經結束執行後,不能再重新啟動。 
2. Thread的終結 Thread的啟動會執行run方法,當run中的方法執行完最後一行後,執行緒就自然終結。 停止執行緒 public final void stop()
     已過時。強迫執行緒停止執行。 3. Thread的暫停、掛起、恢復 休眠 public static void sleep(long millis) throws InterruptedException
     在指定的毫秒數內讓當前正在執行的執行緒休眠(暫停執行),此操作受到系統計時器和排程程式精度和準確性的影響。該執行緒不丟失任何監視器的所屬權。  public static void sleep(long millis, int nanos) throws InterruptedException
     在指定的毫秒數加指定的納秒數內讓當前正在執行的執行緒休眠(暫停執行),此操作受到系統計時器和排程程式精度和準確性的影響。該執行緒不丟失任何監視器的所屬權。      sleep()方法的最簡單的描述是:呼叫者會睡眠一段制定的時間。 4. Thread的善後 執行緒連線 public final void join(long millis) throws InterruptedException
     等待該執行緒終止的時間最長為 millis 毫秒。超時為 0 意味著要一直等下去。 public final void join(long millis, int nanos) throws InterruptedException
     等待該執行緒終止的時間最長為 millis 毫秒 + nanos 納秒。 public final void join() throws InterruptedException
     等待該執行緒終止。 

四、兩種停止Thread的方式

1. 標記
public class RandomCharacterGenerator extends Thread {
	private volatile boolean done = false;
	
	@Override
	public void run() {
		// ...
		while (!done) {
			// ...
		}
		// ...
	}
	
	public void setDone() {
		done = true;
	}
}

問題是會出現延遲 2. 中斷
class InterruptedThread extends Thread {
	
	@Override
	public void run() {
		if (!isInterrupted()) {
			// 
		}
	}
}
public boolean isInterrupted()
     測試執行緒是否已經中斷。執行緒的中斷狀態 不受該方法的影響。 
     執行緒中斷被忽略,因為在中斷時不處於活動狀態的執行緒將由此返回 false 的方法反映出來。 
     返回:
     如果該執行緒已經中斷,則返回 true;否則返回 false。 public static boolean interrupted()
     測試當前執行緒是否已經中斷。執行緒的中斷狀態 由該方法清除。換句話說,如果連續兩次呼叫該方法,則第二次呼叫將返回false(在第一次呼叫已清除了其中斷狀態之後,且第二次呼叫檢驗完中斷狀態前,當前執行緒再次中斷的情況除外)。 
     執行緒中斷被忽略,因為在中斷時不處於活動狀態的執行緒將由此返回 false 的方法反映出來。 

     返回:
     如果當前執行緒已經中斷,則返回 true;否則返回 false。

五、Runnable Interface

使用Runnable介面的執行緒
public class OurClass {
	
	public static void main(String[] args) {
		RunnableClass ourRunnableClass = new RunnableClass();
		Thread thread = new Thread(ourRunnableClass);
		thread.start();
	}
}

class RunnableClass implements Runnable {
	@Override
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println("Helo World! " + i);
		}
	}
}


檢視Runnable原始碼

六、Thread與物件

判別當前的Thread public static Thread currentThread()
     返回對當前正在執行的執行緒物件的引用。  執行緒的生命週期 public final boolean isAlive()
     測試執行緒是否處於活動狀態。如果執行緒已經啟動且尚未終止,則為活動狀態。 執行緒的命名 public final void setName(String name)
     改變執行緒名稱,使之與引數 name 相同。
     首先呼叫執行緒的 checkAccess 方法,且不帶任何引數。這可能丟擲 SecurityException。
    
public final String getName()
     返回該執行緒的名稱。

public Thread(String name)
     分配新的 Thread 物件。這種構造方法與 Thread(null, null, name) 具有相同的作用。     

public Thread(ThreadGroup group, String name)
     分配新的 Thread 物件。這種構造方法與 Thread(group, null, name) 具有相同的作用。      每個執行緒都設定名字便於問題的跟蹤與定位。