SCJP筆記_章九_線程

第九章 線程html

 

 

9.1 定義、實例化並啓動線程java

考試目標4.1 使用java.lang.Thread和java.lang.Runnable編寫代碼,定義、實例化並啓動新線程。編程

 

9.1.1 定義線程安全

 

擴展java.lang.Thread類,重寫run()方法。併發

class MyThread extends Thread{
 public void run(){
 System.out.println("Important job running in MyThread");
 } 
}

  

實現java.lang.Runnable,實現run()方法。函數

class MyRunnable implements Runnable{
 public void run(){
 System.out.println("Important job running in MyRunnable");
 } 
}

 

 

9.1.2 實例化線程spa

 每一個執行線程都是做爲Thread類的一個實例開始的。線程

對於擴展Thread類而定義的線程實例化方式以下:設計

MyThread t = new MyThread();

對於實現Runnable接口而定義的線程實例化方式以下:code

MyRunnable r = new MyRunnable(); 
Thread t = new Thread(r);

  

 

Thread類的構造函數:
Thread()
Thread(Runnable target)
Thread(Runnable target,String name)
Thread(String name)
9.1.3 啓動線程
t.start();

在調用start()方法後,發生:

啓動新的執行線程(具備新的調用棧)。

線程重新狀態轉到可運行狀態(runnable state)。

當線程得到執行機會時,會運行它的目標run()方法。 

 

Thread.currentThread()用來獲取當前線程引用。

Thread.getName()用來得到線程的名字。

 

啓動並運行多個線程:

每一個線程都會啓動,並且每一個線程都將運行到結束。可是順序,優先沒有絕對保證。

當線程的目標run()方法結束時,該線程就完成了。死線程不能再次調用start()方法。

只要線程已經啓動過,它就永遠不能再次啓動。

 

線程調度器:

可運行線程編程運行中線程的順序是沒有保證的。

java.lang.Thread類中控制(影響)線程的方法:

public static void sleep(long millis) throws InterruptedException public static void yield() 
public final void join() throws InterruptedException 
public final void setPriority(int newPriority) 
//默認是5,值越大,優先越高 1-10

 

java.lang.Object類中控制(影響)線程的方法:

public final void wait() throws InterruptedException 
public final void notify()	//喚醒單個線程 
public final void notifyAll() 	//喚醒全部線程

  

  

9.2 線程狀態與轉變

考試目標4.2 識別線程可以位於哪些狀態,並肯定線程能從一種狀態轉變成另外一種狀態的方式。

 

9.2.1 線程狀態

 

新狀態--new

可運行狀態--runable

運行中狀態--running

等待/阻塞/睡眠狀態--waiting/blocked/sleeping

死狀態--dead

 

線程狀態轉換

 

9.2.2 阻止線程執行

一個線程被踢出「運行中」狀態,而不是被送回「可運行」或「死」狀態。

即:睡眠,等待,由於須要對象的鎖而被阻塞。

 

9.2.3 睡眠

Thread的兩個靜態方法:

public static void sleep(long millis) throws InterruptedException                      //millis是毫秒

public static void sleep(long millis,int nanos) throws InterruptedException      //nanos是納秒

 

9.2.4 線程優先級和yield()

 

調度器在優先級上是沒有保證的,主要是看它「喜歡。。仍是不喜歡」,真夠無奈的。

 

設置線程的優先級

t.setPriority(int i);

 

yield()方法

Thread的靜態方法yield(),讓當前的「運行中」線程回到「可運行」狀態,讓步給具備相同優先級的其餘「可運行」線程,但這是沒有任何保證的。

 

join()方法

Thread的非靜態方法join()讓當前線程加入到引用的線程尾部,這意味着調用方法的線程完成(死狀態)以前,主線程不會變爲可運行的。 

public final void join() //要一直等待該線程結束 throws InterruptedException

public final void join(long millis) //millis爲0表示要一直等下去 throws InterruptedException

public final void join(long millis, int nanos) throws InterruptedException

 

9.3 同步代碼

考試目標4.3 給定一個場景,編寫代碼,恰當地使用對象鎖定來保護靜態變量或實例變量,使它們不出險併發訪問問題。

 

9.3.1 同步和鎖 synchronized

  • 只能同步方法(或代碼塊),不能同步變量或類
  • 每一個對象只有一個鎖。換句話說同一時間只有一個線程可使用該對象的同步方法或代碼塊。
  • 沒必要同步類中的所有方法。類能夠同時具備同步方法和非同步方法。
  • 一旦一個線程得到了對象的鎖,就沒有任何其餘線程能夠進入(該對象的)類中的任務同步方法。
  • 若是類同事具備同步和非同步方法,則多個線程仍然可以訪問該類的非同步方法。
  • 若是線程進入睡眠,則它會保持已有的任何鎖,不會釋放他們。
  • 線程能夠得到多個鎖,即線程能夠同時得到多個對象的鎖。

 靜態方法可否同步

能夠,靜態代碼塊也能夠。例如:

 

public static synchronized int getCount(){
 return count; 
} 
public static int getCount(){
  //注意synchronized關鍵字後面括號裏的內容:即要鎖的類或對象
 synchronized(MyClass.class){
   return count; 
 }
}

  

 

 

若是線程不能得到鎖會怎麼樣?

會阻塞,等鎖釋放。

 

什麼時候須要同步?

書雲:對於複雜的狀況「若是你不想它的話,你的生命就會更長、更愉快。真的如此,咱們沒有撒謊。」

 

線程安全類

StringBuffer等

 

9.3.2 線程死鎖

  • 當代碼等待從對象刪除鎖而迫使線程執行暫停時,死鎖就發生了。
  • 當被鎖的對象試圖訪問另外一個被鎖的對象,而該對象又要訪問第一個被鎖的對象時,就會發生死鎖現象。換句話說,兩個線程都在等待對方釋放鎖,所以,這些鎖永遠不會釋放!
  • 死鎖是一種糟糕的設計,不該當讓它發生。

 

9.4 線程交互

考試目標4.4 給定一個場景,編寫代碼,恰當地使用wait()、notify()和notifyAll()方法。

 

必須在同步方法內調用wait()、notify()和notifyAll()方法!線程不能調用對象上的等待或通知方法,除非它擁有該對象的鎖。

9.4.1 當多個線程等待時使用notifyAll()

 

在循環中使用wait()

相關文章
相關標籤/搜索