一、wait與notify、notifyAll
開發過程中,對線程阻塞與喚醒我們都知道可以使用object的wait和notify,notifyAll實現。
以上方式的缺點:notify是隨機喚醒某個阻塞的線程,notifyAll喚醒所有阻塞線程,不能實現喚醒指定線程。
二、LockSupport
後來瞭解到LockSupport類,它位於java.util.concurrent.locks,提供了park()與unpark(thread)結合可以實現
操作。
park
阻塞某線程,調用本地方法實現,源碼如下:
public static void park() {
unsafe.park(false, 0L);
}
public native void park(boolean var1, long var2);
API解釋
park
public static void park(Object blocker)
爲了線程調度,在許可可用之前禁用當前線程。
如果許可可用,則使用該許可,並且該調用立即返回;否則,爲線程調度禁用當前線程,並在發生以下三種情況之一前,使其處於休眠狀態:
其他某個線程調用將當前線程作爲目標調用 unpark;或者
其他某個線程中斷當前線程;或者
該調用不合邏輯地(即毫無理由地)返回。
此方法不 報告是哪個線程導致該方法返回。調用者應該重新檢查最先導致線程暫停的條件。調用者還可以確定返回時該線程的中斷狀態。
unpark(thread)
喚醒指定線程,調用本地方法實現,源碼如下:
public static void unpark(Thread thread) {
if (thread != null)
unsafe.unpark(thread);
}
public native void unpark(Object var1);
API解釋
unpark
public static void unpark(Thread thread)
如果給定線程的許可尚不可用,則使其可用。如果線程在 park 上受阻塞,則它將解除其阻塞狀態。否則,保證下一次調用 park 不會受阻塞。如果給定線程尚未啓動,則無法保證此操作有任何效果。
參數:
thread - 要執行 unpark 操作的線程;該參數爲 null 表示此操作沒有任何效果。
三、測試代碼
public class TestPark {
public static void main(String[] args) {
System.out.println(System.currentTimeMillis() + "TestPark開始測試====");
System.out.println("該線程線程號爲:" + Thread.currentThread().getName());
System.out.println(System.currentTimeMillis() + "將該線程實體傳入Test中");
new Thread(new TestThread(Thread.currentThread())).start();
System.out.println(System.currentTimeMillis() + "該線程停止====");
LockSupport.park();
System.out.println(System.currentTimeMillis() + "線程恢復======");
}
}
public class TestThread implements Runnable {
private Thread thread;
public TestThread() {
}
public TestThread(Thread thread) {
this.thread = thread;
}
@Override
public void run() {
try {
System.out.println(System.currentTimeMillis() + "等待開始");
Thread.sleep(1000);
System.out.println(System.currentTimeMillis() + "等待結束");
} catch (Exception e) {
System.out.println("等待失敗");
}
LockSupport.unpark(thread);
System.out.println("thread:" + thread.getId() + "釋放許可");
}
}