線程狀態
- 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();
}
}

