java阻塞唤醒线程之LockSupport

1 场景

这里介绍一个jdk自带的线程阻塞、唤醒工具LockSupport

此工具类属于juc包的一部分,所在包路径:java.util.concurrent.locks.LockSupport

2 思维导图

已将LockSupport相关的内容整理为思维导图如下:

java阻塞唤醒线程之LockSupport.png

3 常用方法

LockSupport的使用方法,均为static方法

常用方法如下:

方法 描述
LockSupport.park() 持续阻塞当前线程
LockSupport.park(blocker) 持续阻塞当前线程
LockSupport.parkNanos(nanos) 超时时间nanos内,阻塞当前线程
LockSupport.parkNanos(blocker,nanos)
nanos为纳秒
超时时间nanos内,阻塞当前线程
LockSupport.parkUntil(deadline) 截止时间deadline内,阻塞当前线程
LockSupport.parkUntil(blocker,deadline)
deadline为毫秒
截止时间deadline内,阻塞当前线程

4 优点

使用LockSupport,好处是不会出现死锁,可以先unpark后park,无论unpark多少此,park一次,即可消费掉。

坏处是,和常见的线程类方法不一样的是,当线程被中断后,不会抛出异常InterruptedException,同时有可能有不可预料的异常,导致阻塞结束。

The call spuriously (that is, for no reason) returns.

5 代码建议

如手动park阻塞后,如需手动unpark唤醒。可参考如下代码:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

public class LockSupportContext {
    private AtomicBoolean lockFlag = new AtomicBoolean(false);
    private Thread lockThread = new Thread();
    public boolean lock() {
        lockThread = Thread.currentThread();
        lockFlag.set(true);
        LockSupport.park(this);
        while (!lockFlag.compareAndSet(false, true)) {
            // 无限加锁(如考虑非可控的中断,可更改为if,只加一次锁)
            LockSupport.park(this);
            if (lockThread.isInterrupted()) {
                // 解锁失败
                return false;
            }
        }
        // 解锁成功
        return true;
    }
    public void unlock() {
        lockFlag.set(false);
        LockSupport.unpark(lockThread);
    }
    
    public static void main(String[] args) throws Exception {
        LockSupportContext lockSupportContext = new LockSupportContext();
        Thread thread = new Thread(() -> {
            System.out.println("子线程-加锁开始");
            boolean lockFlag = lockSupportContext.lock();
            System.out.println("子线程-加锁结束,解锁结果:" + lockFlag);
        });
        thread.start();
        Thread.sleep(TimeUnit.SECONDS.toMillis(2));
        
        System.out.println("主线程解锁");
        lockSupportContext.unlock();
    }
}

你可能感兴趣的:(java阻塞唤醒线程之LockSupport)