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();
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

推荐阅读更多精彩内容