LockSupport是一個工具類,提供了基本的線程阻塞和喚醒功能,它是建立鎖和其餘同步組件的基礎工具,內部是使用sun.misc.Unsafe類實現的。ide
LockSupport和使用它的線程都會關聯一個許可,park方法表示消耗一個許可,調用park方法時,若是許可可用則park方法返回,若是沒有許可則一直阻塞直到許可可用。unpark方法表示增長一個許可,屢次調用並不會積累許可,由於許可數最大值爲1。工具
park(): 阻塞當前線程,直到unpark方法被調用或當前線程被中斷,park方法纔會返回。線程
park(Object blocker): 同park()方法,多了一個阻塞對象blocker參數。對象
parkNanos(long nanos): 同park方法,nanos表示最長阻塞超時時間,超時後park方法將自動返回。blog
parkNanos(Object blocker, long nanos): 同parkNanos(long nanos)方法,多了一個阻塞對象blocker參數。同步
parkUntil(long deadline): 同park()方法,deadline參數表示最長阻塞到某一個時間點,當到達這個時間點,park方法將自動返回。(該時間爲從1970年到如今某一個時間點的毫秒數)it
parkUntil(Object blocker, long deadline): 同parkUntil(long deadline)方法,多了一個阻塞對象blocker參數。io
unpark(Thread thread): 喚醒處於阻塞狀態的線程thread。class
子線程執行LockSupport.park(),因爲沒有許可,進入阻塞狀態。主線程3秒後調用unpark方法給子線程增長了一個許可,park方法返回,子線程被喚醒繼續執行。thread
public class Demo { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { System.out.println("do something start"); LockSupport.park(); System.out.println("do something end"); }); thread.start(); Thread.sleep(3000); System.out.println("給子線程thread增長一個許可"); LockSupport.unpark(thread); } } /* * 輸出結果: * do something start * 給子線程thread增長一個許可 * do something end */
先unpark增長許可,後park消費許可也是能夠的。unpark會給thread增長一個許可,此時調用park方法,因爲許但是可用的,因此park方法直接返回了。
public class Demo { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println("do something start"); System.out.println("子線程thread給本身增長一個許可"); LockSupport.unpark(Thread.currentThread()); LockSupport.park(); System.out.println("do something end"); }); thread.start(); } } /* * 輸出結果: * do something start * 子線程thread給本身增長一個許可 * do something end */
連續調用unpark不會累計許可,許可最大值爲1,第一次park就已經消耗了許可,因此第二次park一直阻塞。
public class Demo { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println("do something start"); LockSupport.unpark(Thread.currentThread()); System.out.println("unpark 1"); LockSupport.unpark(Thread.currentThread()); System.out.println("unpark 2"); LockSupport.park(); System.out.println("park 1"); LockSupport.park(); System.out.println("park 2"); System.out.println("do something end"); }); thread.start(); } } /* * 輸出結果: * do something start * unpark 1 * unpark 2 * park 1 */
經過前面方法介紹能夠看到,park、parkNanos、parkUntil方法都有對應的帶阻塞對象blocker參數的重載方法。Thread類有一個變量爲parkBlocker,對應的就是LockSupport的park等方法設置進去的阻塞對象。
該參數主要用於問題排查和系統監控,在線程dump中會顯示該參數的信息,有利於問題定位。
分別調用park()和park(Object blocker),而後使用jstack查看線程堆棧信息,對比發現後者會多輸出一條阻塞對象的信息:
park():
public class Demo { public static void main(String[] args) { LockSupport.park(); } }
park(Object blocker):
public class Demo { public static void main(String[] args) { LockSupport.park(new Demo()); } }
park和unpark方法的調用不須要獲取鎖。
先調用unpark方法後調用park方法依然能夠喚醒。
park方法響應中斷,線程被中斷後park方法直接返回,可是不會拋InterruptedException異常。
unpark方法是直接喚醒指定的線程。