• LockSupport线程工具类解析


    在以往的线程交互中,我们唤醒线程或者阻塞线程一般都是用notify/wait/await等等函数,但是还是不够灵活。例如说,我现在有十个线程,如果是我想唤醒或者挂起这其中的一部分线程的话,那我可以使用Condition,将这部分线程分队列,也就是ReentrantLock里面的,newCondition,但是此时我的需求是想要唤醒第七个线程,然后让第二个线程阻塞,那么不管是Condition还是wait,notify,都显得麻烦,力不从心,因此为了解决这个问题,就出现了这个线程工具类Locksupport

    LockSupport概述

    LockSupport是为了方便的对线程进行交互,而开发出来的线程工具类。基于UnSafe来实现的,最主要的作用是挂起和唤醒线程。

    对于LockSupport来说,用的最多的以及最重要的方法,就是Park()系列方法和UnPark()系列方法了。

    park方法

    pack

    方法 解释
    park(Object) 挂起当前线程
    parkNanos(Object,long) 指定了一个挂起时间(相对于当前的时间),时间到后自动被唤醒;例如1000纳秒后自动唤醒
    parkUntil(Object,long) 指定一个挂起时间(绝对时间),时间到后自动被唤醒;例如2018-02-1221点整自动被唤醒。
    park() 和park(Object)相比少了挂起前为线程设置blocker、被唤醒后清理blocker的操作。
    parkNanos(long) 和parkNanos(Object,long)类似,仅少了blocker相关的操作
    parkUntil(long) 和parkUntil(Object,long)类似,仅少了blocker相关的操作
    • park(Object) 源码
    public static void park(Object blocker) {
                //获取当前线程
                Thread t = Thread.currentThread();
                //设置线程parkBlocker
                setBlocker(t, blocker);
                //阻塞线程
                UNSAFE.park(false, 0L);
                //清除parkBlocker
                setBlocker(t, null);
            }
    

    可以看到,park是默认阻塞的是当前的线程。举个代码的例子

    public class LockSupportDemo1 {
        public static void main(String[] args) {
            System.out.println("开始");
            LockSupport.park();
            System.out.println("结束");
        }
    }
    

    这个程序只会输出开始,而且一直都不会结束,因为主线程已经被阻塞了。但是没有其他的线程唤醒它,就会被一直阻塞住。在别的线程调用UnPark方法的时候,并且把当前线程作为参数时,那个因为调用了park方法而被阻塞的线程才会被唤醒

    unPark方法

        public static void unpark(Thread thread) {
            if (thread != null)
                UNSAFE.unpark(thread);
        
    

    这个方法其实很简单,传入需要唤醒的线程的引用,然后就会唤醒那个线程。另外还有一个特点就是,当线程在调用park()之前调用了unPark,那么park方法也会被马上唤醒。像这样

    public class LockSupportDemo1 {
        public static void main(String[] args) {
            System.out.println("开始");
            LockSupport.unpark(Thread.currentThread());
            LockSupport.park();
            System.out.println("结束");
        }
    }
    

    像这样,代码的输出仍然会是

    开始
    结束
    

    应用代码示例

    要求:两个线程交替输出1A2B......,思路,这个时候就可以用到LockSupport,当输出完一次之后,就休眠当前线程,唤醒另一个线程去输出

    /**
     * 两个线程交替输出1A2B......
     */
    public class Test2 {
    static  Thread t1 = null;
       static Thread t2 = null;
        public static void main(String[] args) {
    
    
            char[] num = "123456789".toCharArray();
            char[] words = "ABCDEFGHI".toCharArray();
    
    
            t1 = new Thread(() ->{
               for (int i=0;i<num.length;i++){
                   System.out.println(num[i]);
                   LockSupport.park();
                   LockSupport.unpark(t2);
               }
            },"t1");
    
            t2 = new Thread(() ->{
                for (int i=0;i<words.length;i++){
                    System.out.println(words[i]);
                    LockSupport.unpark(t1);
                    LockSupport.park();
                }
            },"t2");
            t1.start();
            t2.start();
    
        }
    }
    
    

  • 相关阅读:
    微博短地址识别正则表达式
    VM 虚拟机, linux mount windows的共享目录,php报错:Fatal error: Unknown: Failed opening required
    新贵 轻雅 100 数字键 numlock问题
    [转]人大常委会委员:文理分科降低民族整体素质
    NTFS变RAW后的修复
    西门子plc视频教程
    ProE 工程图教程系列3 Pro/E消息区域中错误、警告消息的处理
    奥运会上同时升起三面五星红旗
    亦歌 在线听歌网站
    [转]国内外常用钢号对照表
  • 原文地址:https://www.cnblogs.com/blackmlik/p/12960716.html
Copyright © 2020-2023  润新知