1. 介绍
LockSupport是一个非常方便实用的线程阻塞工具,它可以在线程内任意位置阻塞线程。和Thread.suspend()相比,它弥补了由于resume()发生在前,导致线程无法继续执行的情况。和Object.wait()相比,它不需要先获得某个对象的锁,也不会抛出InterruptedException异常。
2. 主要方法
都是静态方法
public static void park();
public static void park(Object blocker);
public static void parkNanos(Object blocker, long nanos);
public static void parkUntil(Object blocker, long deadline);
public static void parkNanos(long nanos);
public static void parkUntil(long deadline);
public static void unpark(Thread thread);
3. 原理
LockSupport类使用类似信号量的机制,它为每一个线程准备了一个许可,如果许可可用,那么park()函数会立即返回,并且消费这个许可,如果许可不可用就会阻塞。而unpark则使得一个许可变为可用,但是许可不能累加,永远只有一个。
这个特点使得:即使unpark()发生在park()前,它也可以使得下一个park()操作立即返回。
park()挂起状态的线程不像suspend()那样给出一个Runnable状态,它会给出WAITING状态,标注是park()引起的。
"Thread-0" #12 prio=5 os_prio=0 tid=0x00007f471438d800 nid=0x4c15 waiting on condition [0x00007f46febe7000]
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.xhx.java.Test01.lambda$test01$0(Test01.java:20)
at com.xhx.java.Test01$$Lambda$1/660143728.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
LockSupport.park(this);
为当前线程设置一个阻塞对象,这个阻塞对象会出现在线程dump中,这样分析问题,将更加方便。
"Thread-0" #12 prio=5 os_prio=0 tid=0x00007f83d430d800 nid=0x4cee waiting on condition [0x00007f83b8aeb000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000782c34ba8> (a com.xhx.java.Test01)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at com.xhx.java.Test01.lambda$test01$0(Test01.java:20)
at com.xhx.java.Test01$$Lambda$1/523691575.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
4. 示例
public class Test01 {
@Test
public void test01() throws Exception{
Thread th = new Thread(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("开始阻塞");
LockSupport.park();
System.out.println("程序结束");
});
th.start();
LockSupport.unpark(th);
System.out.println("解除阻塞");
Thread.sleep(2000);
}
}
5. 中断
除了定时阻塞,LockSuport.park()还能支持中断影响,但是不会抛出InterruptedException异常,它只会默默的返回,但是我们能从Thread.interrupted()中获得中断标记