美文网首页多线程与高并发jdk
java阻塞唤醒线程之LockSupport

java阻塞唤醒线程之LockSupport

作者: 水煮鱼又失败了 | 来源:发表于2021-05-30 17:08 被阅读0次

    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

        本文链接:https://www.haomeiwen.com/subject/xacmsltx.html