是什么
LockSupport是一個線程阻塞工具類,所有的方法都是靜態(tài)方法,可以讓線程在任意位置阻塞,當(dāng)然阻塞之后肯定得有喚醒的方法。
有什么用
接下面我來看看LockSupport有哪些常用的方法。主要有兩類方法:park和unpark。
public static void park(Object blocker); // 暫停當(dāng)前線程
public static void parkNanos(Object blocker, long nanos); // 暫停當(dāng)前線程,不過有超時時間的限制
public static void parkUntil(Object blocker, long deadline); // 暫停當(dāng)前線程,直到某個時間
public static void park(); // 無期限暫停當(dāng)前線程
public static void parkNanos(long nanos); // 暫停當(dāng)前線程,不過有超時時間的限制
public static void parkUntil(long deadline); // 暫停當(dāng)前線程,直到某個時間
public static void unpark(Thread thread); // 恢復(fù)當(dāng)前線程
public static Object getBlocker(Thread t);
為什么叫park呢,park英文意思為停車。我們?nèi)绻裈hread看成一輛車的話,park就是讓車停下,unpark就是讓車啟動然后跑起來。
我們寫一個例子來看看這個工具類怎么用的。
public class LockSupportDemo {
public static Object u = new Object();
static ChangeObjectThread t1 = new ChangeObjectThread("t1");
static ChangeObjectThread t2 = new ChangeObjectThread("t2");
public static class ChangeObjectThread extends Thread {
public ChangeObjectThread(String name) {
super(name);
}
@Override public void run() {
synchronized (u) {
System.out.println("in " + getName());
LockSupport.park();
if (Thread.currentThread().isInterrupted()) {
System.out.println("被中斷了");
}
System.out.println("繼續(xù)執(zhí)行");
}
}
}
public static void main(String[] args) throws InterruptedException {
t1.start();
Thread.sleep(1000L);
t2.start();
Thread.sleep(3000L);
t1.interrupt();
LockSupport.unpark(t2);
t1.join();
t2.join();
}
}
運(yùn)行的結(jié)果如下:
in t1
被中斷了
繼續(xù)執(zhí)行
in t2
繼續(xù)執(zhí)行
這兒park和unpark其實(shí)實(shí)現(xiàn)了wait和notify的功能,不過還是有一些差別的。
-
park不需要獲取某個對象的鎖 - 因?yàn)橹袛嗟臅r候
park不會拋出InterruptedException異常,所以需要在park之后自行判斷中斷狀態(tài),然后做額外的處理
我們再來看看Object blocker,這是個什么東西呢?這其實(shí)就是方便在線程dump的時候看到具體的阻塞對象的信息。
"t1" #10 prio=5 os_prio=31 tid=0x00007f95030cc800 nid=0x4e03 waiting on condition [0x00007000011c9000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
// `下面的這個信息`
at com.wtuoblist.beyond.concurrent.demo.chapter3.LockSupportDemo$ChangeObjectThread.run(LockSupportDemo.java:23) //
- locked <0x0000000795830950> (a java.lang.Object)
還有一個地方需要注意,相對于線程的stop和resume,park和unpark的先后順序并不是那么嚴(yán)格。stop和resume如果順序反了,會出現(xiàn)死鎖現(xiàn)象。而park和unpark卻不會。這又是為什么呢?還是看一個例子
public class LockSupportDemo {
public static Object u = new Object();
static ChangeObjectThread t1 = new ChangeObjectThread("t1");
public static class ChangeObjectThread extends Thread {
public ChangeObjectThread(String name) {
super(name);
}
@Override public void run() {
synchronized (u) {
System.out.println("in " + getName());
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
LockSupport.park();
if (Thread.currentThread().isInterrupted()) {
System.out.println("被中斷了");
}
System.out.println("繼續(xù)執(zhí)行");
}
}
}
public static void main(String[] args) {
t1.start();
LockSupport.unpark(t1);
System.out.println("unpark invoked");
}
}
t1內(nèi)部有休眠1s的操作,所以unpark肯定先于park的調(diào)用,但是t1最終仍然可以完結(jié)。這是因?yàn)?code>park和unpark會對每個線程維持一個許可(boolean值)
- unpark調(diào)用時,如果當(dāng)前線程還未進(jìn)入park,則許可為true
- park調(diào)用時,判斷許可是否為true,如果是true,則繼續(xù)往下執(zhí)行;如果是false,則等待,直到許可為true
我們再看看jdk的文檔描述

park描述

unpark描述
總結(jié)一下
-
park和unpark可以實(shí)現(xiàn)類似wait和notify的功能,但是并不和wait和notify交叉,也就是說unpark不會對wait起作用,notify也不會對park起作用。 -
park和unpark的使用不會出現(xiàn)死鎖的情況 - blocker的作用是在dump線程的時候看到阻塞對象的信息