• LockSupport的用法及原理


     LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,当然阻塞之后肯定得有唤醒的方法。concurrent包是基于AQS (AbstractQueuedSynchronizer)框架的,AQS框架借助于两个类:

    • Unsafe(提供CAS操作)
    • LockSupport(提供park/unpark操作)

    接下面我来看看LockSupport有哪些常用的方法。主要有两类方法:park和unpark。

    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 park(); // 无期限暂停当前线程
    public static void parkNanos(long nanos); // 暂停当前线程,不过有超时时间的限制
    public static void parkUntil(long deadline); // 暂停当前线程,直到某个时间
    public static void unpark(Thread thread); // 恢复当前线程
    public static Object getBlocker(Thread t);

    park函数是将当前调用Thread阻塞,而unpark函数则是将指定线程Thread唤醒。与Object类的wait/notify机制相比,park/unpark有两个优点:

    • 以thread为操作对象更符合阻塞线程的直观定义
    • 操作更精准,可以准确地唤醒某一个线程(notify随机唤醒一个线程,notifyAll唤醒所有等待的线程),增加了灵活性。

    为什么叫park呢,park英文意思为停车。我们如果把Thread看成一辆车的话,park就是让车停下,unpark就是让车启动然后跑起来。
    我们写一个例子来看看这个工具类怎么用的。

    package com.springboot.study.tests.lock;
    
    import java.util.concurrent.locks.LockSupport;
    
    /**
     * @Author: guodong
     * @Date: 2021/6/1 16:03
     * @Version: 1.0
     * @Description:
     */
    public class LockSupportDemo {
    
        public static Object u = new Object();
        static ChangeObjectThread t1 = new ChangeObjectThread("t1");
        static ChangeObjectThread t2 = new ChangeObjectThread("t2");
    
        public static class ChangeObjectThread extends Thread {
            public ChangeObjectThread(String name) {
                super(name);
            }
    
            @Override
            public void run() {
                synchronized (u) {
                    System.out.println("in " + getName());
                    LockSupport.park();
                        if (Thread.currentThread().isInterrupted()) {
                        System.out.println("被中断了");
                    }
                    System.out.println("继续执行");
                }
            }
    
        }
    
        public static void main(String[] args) throws InterruptedException {
            t1.start();
            Thread.sleep(1000L);
            t2.start();
            Thread.sleep(3000L);
            t1.interrupt();
            LockSupport.unpark(t2);
            t1.join();
            t2.join();
        }
    
    }

    运行的结果如下:

    in t1
    被中断了
    继续执行
    in t2
    继续执行

    这儿park和unpark其实实现了wait和notify的功能,不过还是有一些差别的。

    • park不需要获取某个对象的锁
    • 因为中断的时候park不会抛出InterruptedException异常,所以需要在park之后自行判断中断状态,然后做额外的处理

    总结一下

    • park和unpark可以实现类似wait和notify的功能,但是并不和wait和notify交叉,也就是说unpark不会对wait起作用,notify也不会对park起作用。
    • park和unpark的使用不会出现死锁的情况
    • blocker的作用是在dump线程的时候看到阻塞对象的信息

  • 相关阅读:
    mybatis generator插件开发
    webserver实现
    Linux的selinux
    oracle从备份归档日志的方法集中回收
    百度地图 Android SDK
    Oracle实践--PL/SQL表分区的基础
    js插件---jquery给表格添加行列
    m_Orchestrate learning system---三十四、使用重定义了$的插件的时候最容易出现的问题是什么
    2018十大国产佳片
    javascript对象使用总结
  • 原文地址:https://www.cnblogs.com/jelly12345/p/14837628.html
Copyright © 2020-2023  润新知