以下內容主要總結自《Java多線程編程核心技術》,不定時補充更新。
一、線程的狀態
Java中,線程的狀態有以下6類:NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED。各狀態之間的關系可用下圖表示:
二、常用方法介紹
1、thread.start()和thread.run()的區別
1 public static void main(String[] args) { 2 Thread t = new Thread(); 3 t.start(); 4 System.out.println("main end"); 5 }
調用start()方法啟動線程t,t線程的狀態會從New -> Runnable,t線程和main主線程同時執行。
如果把t.start()改成t.run(),則是普通的調用方法,同步執行,System.out.println("main end")語句必須等t.run()方法執行完畢之后才能執行。
注意:t.run()方法不會改變線程t的狀態,也就是說線程沒有啟動。
2、object.wait()和thread.sleep()的區別
1 private Object obj = new Object(); 2 public void testMethod() throws InterruptedException { 3 synchronized (obj) { 4 obj.wait(); 5 System.out.println("testMethod end"); 6 } 7 }
wait()方法主要用在synchronized同步方法或者同步塊中,意味着調用object.wait()之前必須先獲取鎖,調用wait()方法之后釋放鎖,線程進入waiting狀態。常見用法如上所示。如果有其他線程通過調用object.notify()或者object.notifyAll()方法時,線程必須再次獲取到obj鎖,然后才能繼續執行obj.wait()后的語句,即打印 "testMethod end"。obj.wait(timeout)方法類似,也需要先釋放鎖。
wait()方法是Object類的方法,而sleep(timeout)方法是Thread類的方法。線程調用sleep(timeout)方法,狀態從runnable -> timed_waiting,但是不釋放鎖。
3、interrupt()方法
當線程調用interrupt()方法時,只是設置了線程的中斷狀態。 也就是說如果線程處於runnable或者blocked狀態的時候,調用interrupt()方法並不會終止線程。於是,我想當然的理解如果線程處於waiting或者timed_waiting狀態時,調用interrupt方法會拋出異常,從而終止線程。
然后發現錯了。見如下代碼:
1 private ReentrantLock lock = new ReentrantLock(); 2 private Condition condition = lock.newCondition(); 3 public void testMethod() { 4 try { 5 lock.lock(); 6 System.out.println("wait begin"); 7 condition.awaitUninterruptibly(); 8 System.out.println("wait end"); 9 } finally { 10 lock.unlock(); 11 } 12 }
condition.awaitUninterruptibly()方法不需要捕獲InterruptedException異常,意味着如果線程通過調用awaitUninterruptibly從而使得線程狀態為waiting,並不會因為調用interrupt()方法而中斷。實際測試,線程狀態不響應interrupt方法,只有通過condition.singal或者singalAll才能喚醒線程。
實際測試,wait(), wait(timeout), join(), sleep(timeout), await(), await(timeout)等方法都是可以被interrupt()方法中斷的。
三、synchronized關鍵字
1、synchronized(object): 同步方法或者代碼塊,鎖是一個對象。
2、synchronized(this): this指的是當前對象。
3、針對靜態方法,比如synchronized public static void testMethod(),鎖是當前的Class類。
4、如果代碼拋出異常,鎖自動釋放。