zoukankan      html  css  js  c++  java
  • 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();
    
        }
    }
    
    

  • 相关阅读:
    [Android]Android开发艺术探索第13章笔记
    [Android]Android性能优化
    [设计模式]单例模式
    [设计模式]享元模式
    [Android]《Android艺术开发探索》第一章读书笔记
    1.传入:”Welome to Beijing”改为 “Beijing to Welcome” 将字符串按照单词进行逆序,空格作为划分单词的唯一条件
    关于ubuntu.18.04的安装注意事项
    String和Date,Timestamp之间的转换
    判断图片色彩模式 CYMK || RGB
    java copy file
  • 原文地址:https://www.cnblogs.com/blackmlik/p/12960716.html
Copyright © 2011-2022 走看看