关于“LockSupport.park”

来自Wikioe
跳到导航 跳到搜索


关于

LockSupport (Java Platform SE 8 ):[1]
    These methods are designed to be used as tools for creating higher-level synchronization utilities, and are not in themselves useful for most concurrency control applications.
    这些方法被设计为用于创建更高级别的同步实用程序的工具,而这些方法本身对大多数并发控制应用程序并不有用。


LockSupport 是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞(当然阻塞之后肯定得有唤醒的方法)。

用法

LockSupport.park()LockSupport.unpark() 配合使用,用于“休眠/唤醒当前线程”。

park
public static void park()

    为了线程调度,禁用当前线程,除非许可(permit)可用。

    如果许可可用,则使用该许可,并且该调用立即返回;否则,为线程调度禁用当前线程,并在发生以下三种情况之一以前,使其处于休眠状态:
        1、其他某个线程将当前线程作为目标调用 unpark;
        2、其他某个线程中断当前线程;
        3、该调用不合逻辑地(即毫无理由地)返回。

    此方法并不报告是哪个线程导致该方法返回。调用者应该重新检查最先导致线程暂停的条件。调用者还可以确定线程返回时的中断状态。


unpark
public static void unpark(Thread thread)

    如果给定线程的许可尚不可用,则使其可用。如果线程在上受阻塞,则它将解除其阻塞状态。否则,保证下一次调用不会受阻塞。如果给定线程尚未启动,则无法保证此操作有任何效果。

    参数:
        thread 一要执行 unpark 操作的线程;该参数为表示此操作没有任何效果。
示例[2]
import java.util.concurrent.locks.LockSupport;

public class LockSupportTest2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            System.out.println("t1 线程 开始执行");
            System.out.println("t1 线程 park()  ");
            LockSupport.park();
            System.out.println("t1 线程 继续执行");
            System.out.println("t1 线程 当前的 Interrupt 状态:"+Thread.currentThread().isInterrupted());
        });

        t1.start();
        Thread.sleep(1000L);
        // unpark t1线程
        LockSupport.unpark(t1);
    }
}
tl 线程 开始执行
tl 线程 park()
tl 线程 继续执行
tl 线程 当前的 Interrupt 状态:false


LockSupport.park(Object blocker)LockSupport.getBlocker(Thread thread) 配合使用,可以进行自定义数据传输。

  • blocker 为线程 thread 中定义的需要传输的数据类型。
示例[2]
import java.util.HashMap;
import java.util.concurrent.locks.LockSupport;

public class LockSupportTest {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            System.out.println("t1 线程 开始执行");
            System.out.println("t1 线程 parkNanos()  ");
            HashMap blocker = new HashMap();
            blocker.put("reason","测试LockSupport的park的blocker");
            blocker.put("code","1000");
            LockSupport.parkNanos(blocker, 2000*1000*2000L);
            System.out.println("t1 线程 继续执行");
            System.out.println("t1 线程 当前的 Interrupt 状态:" + Thread.currentThread().isInterrupted());
        });
        t1.start();
        Thread.sleep(1000L);
        Object blocker = LockSupport.getBlocker(t1);
        System.out.println("t1 线程 的 blocker:" + blocker);
        Thread.sleep(1000*100L);
    }
}
tl 线程 开始执行
tl 线程 parkNanos()
tl 线程 的 blocker: {reason=测试LockSupport的park的blocker, code=1000}
tl 线程 继续执行
tl 线程当前的 Interrupt 状态:false

区别

LockSupport.park 与 Thread.sleep、Object.wait 语义类似,但有如下区别:

  1. LockSupport.park 方法会进入 WAITING 状态,而 LockSupport.parkNanos 会进入 TIMED_WAITING 状态。
    【Thread.sleep 进入 TIMED_WAITING 状态; Object.wait 进入 WAITING 或 TIMED_WAITING 状态】
  2. LockSupport.park 不依赖 monitor 锁(与 synchronized 无关),所以不涉及锁的释放与否
    【Thread.sleep 也不涉及锁的释放; 但 Object.wait 将会释放锁】
  3. LockSupport.park 不会抛出受检查异常,不会吞掉 interrupt 标志位
    【Thread.sleep 与 Object.wait 线程被打断的时候会抛出异常,而且 catch 代码块中得到的 interrupt 状态永远是 false】
    • 可以通过 Interrupt 的状态来“判断线程是不是被 interrupt 的(“中断标识”为“true”),还是被 unpark 或者到达指定休眠时间(“中断标识”为“false”)”。
  4. LockSupport.park 和 LockSupport.unpark 的使用不会出现死锁的情况。

参考