線程狀態
- NEW(初始化狀態)
線程通過new初始化完成到調用start方法前都處於等待狀態。
- RUNNABLE(可執行狀態)
線程執行start方法后就處於可以行狀態。
- BLOCKED(阻塞狀態)
notify方法被調用后線程被喚醒,但是這時notify的synchronized代碼段並沒有執行完,同步鎖沒有被釋放,所以線程處於BLOCKED狀態。直到notify的synchronized代碼段執行完畢鎖被釋放,線程才回到wait所在的synchronized代碼段繼續執行。
- WAITING(等待狀態)
調用sleep或是wait方法后線程處於WAITING狀態,等待被喚醒。
- TIMED_WAITING(等待超時狀態)
調用sleep或是wait方法后線程處於TIMED_WAITING狀態,等待被喚醒或時間超時自動喚醒。
- TERMINATED(終止狀態)
在run方法結束后線程處於結束狀態。
方法一、使用Lock + Condition 實現喚醒指定的部分線程
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Test { public static Lock lock = new ReentrantLock(); public static int count = 0; public static Condition conditionA = lock.newCondition(); public static Condition conditionB = lock.newCondition(); public static void main(String[] args) { Thread t1 = new Thread() { @Override public void run() { lock.lock(); if (count < 5) { System.out.println("線程1未達到業務要求,暫停中,等待線程2處理到達到要求后喚醒"); try { conditionA.await();// 暫停線程並釋放鎖 System.out.println("conditionA被喚醒"); conditionB.await(); System.out.println("conditionB被喚醒"); System.out.println("我是線程1后面的代碼"); } catch (InterruptedException e) { e.printStackTrace(); } } lock.unlock(); } }; Thread t2 = new Thread() { @Override public void run() { lock.lock(); while (count < 10) { count++; System.out.println("線程2業務處理中: " + count); try { Thread.sleep(1000); if (count == 5) { conditionA.signal(); System.out.println("喚醒線程1"); lock.unlock();// 調用signal()方法后,線程2並不會釋放鎖,需要手動釋放線程2才會執行 } } catch (InterruptedException e) { e.printStackTrace(); } } try { lock.lock();// 不加這個會報java.lang.IllegalMonitorStateException System.out.println("等待3秒后conditionB會被喚醒"); Thread.sleep(3000); conditionB.signal(); } catch (InterruptedException e) { e.printStackTrace(); } lock.unlock();// 這里釋放鎖,線程2執行完,線程1才會執行 } }; t1.start(); t2.start(); } }
方法二、使用Java6引入的LockSupport這個類
import java.util.concurrent.locks.LockSupport; public class TestLockSupport { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(()->{ System.out.println("start"); LockSupport.park(); //一直wait System.out.println("continue"); }); t.start(); Thread.sleep(2000); LockSupport.unpark(t); //指定t線程解除wait態 } }
方法三、synchronized + wait + notify
import java.util.concurrent.TimeUnit; public class TestNotify extends Thread{ public static void main(String[] args) { final Object synObj = new Object(); Thread t1 = new Thread(new Runnable() { @Override public void run() { synchronized(synObj) { System.out.println("1.T1獲取synObj的對象監視器,開始執行同步塊"); try { TimeUnit.SECONDS.sleep(2);//休息一分鍾,不放棄鎖 System.out.println("T1在 wait()時掛起了"); synObj.wait(); System.out.println("T1被其他線程喚醒后並重新獲得synObj的對象監視器,繼續執行"); }catch(InterruptedException e) { e.printStackTrace(); } System.out.println("T1獲取synObj的對象監視器,結束同步塊"); } }; }); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { System.out.println("T2啟動,但是因為有別的線程占用了synObj的對象監視器,則等待別的線程執行synObj.wait來釋放它"); synchronized(synObj) { try { System.out.println("T2獲取synObj的對象監視器,進入同步塊"); synObj.notify(); System.out.println("T2執行synObj.notify()"); TimeUnit.SECONDS.sleep(2); System.out.println("T2結束同步塊,釋放synObj的對象監視器"); }catch(InterruptedException e) { e.printStackTrace(); } } }; }); t2.start(); Thread t3 = new Thread(new Runnable() { @Override public void run() { System.out.println("T3啟動,但是因為有別的線程占用了synObj的對象監視器,則等待別的線程執行synObj.wait來釋放它"); synchronized(synObj) { try { System.out.println("T3獲取synObj的對象監視器,進入同步塊"); synObj.notify(); System.out.println("T3執行synObj.notify()"); TimeUnit.SECONDS.sleep(2); System.out.println("T3結束同步塊,釋放synObj的對象監視器"); }catch(InterruptedException e) { e.printStackTrace(); } } }; }); t3.start(); } }