天天看点

LockSupport示例

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()中获得中断标记