美文网首页
ReentrantLock的Condition选择性通知

ReentrantLock的Condition选择性通知

作者: 勇往直前z | 来源:发表于2019-05-28 17:42 被阅读0次

    今天浏览了并发同步的相关知识,使用ReentrantLock写了个小demo,主要关于选择性通知,在此记录一下。

    1.介绍

    ReentrantLock与synchronized 都是可重入锁、独占锁,ReentrantLock基于AQS,AQS基于CAS。

    2.高级功能

    ①等待可中断
    ReentrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。也就是说正在等待的线程可以选择放弃等待,改为处理其他事情。
    ②可实现公平锁
    即先到先得,通过构造函数ReentrantLock(boolean fair)制定。
    ③可实现选择性通知(锁可以绑定多个条件)
    需要借助于Condition接口与newCondition() 方法,线程对象可以注册在指定的Condition中,从而可以有选择性的进行线程通知,在调度线程上更加灵活。

    3.选择性通知实现

    用简单的代码写了机器人给老板洗澡的过程。以下:
    ①机器人服务

    package com.example.demo.practice;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class RobotService {
    
        private Lock lock = new ReentrantLock(true);
        public Condition washCondition = lock.newCondition();
    
        public void awaitCuoZao() {
            lock.lock();
            System.out.println("等着给老板搓澡...");
            System.out.println("开始等待时间:" + System.currentTimeMillis() + " -- 当前线程:" + Thread.currentThread().getName());
            try {
                washCondition.await();
                System.out.println("结束等待时间:" + System.currentTimeMillis() + " -- 当前线程:" + Thread.currentThread().getName());
                Thread.sleep(3000);
                System.out.println("搓澡完毕!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void awaitMuyulu() {
            lock.lock();
            System.out.println("等着给老板打沐浴露...");
            System.out.println("开始等待时间:" + System.currentTimeMillis() + " -- 当前线程:" + Thread.currentThread().getName());
            try {
                washCondition.await();
                System.out.println("结束等待时间:" + System.currentTimeMillis() + " -- 当前线程:" + Thread.currentThread().getName());
                Thread.sleep(3000);
                System.out.println("打沐浴露完毕!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void awaitChuanyi() {
            lock.lock();
            System.out.println("等着给老板更衣...");
            System.out.println("开始等待时间:" + System.currentTimeMillis() + " -- 当前线程:" + Thread.currentThread().getName());
            try {
                washCondition.await();
                System.out.println("结束等待时间:" + System.currentTimeMillis() + " -- 当前线程:" + Thread.currentThread().getName());
                Thread.sleep(3000);
                System.out.println("更衣完毕!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void signalWash() {
            lock.lock();
            System.out.println("老板:给我洗澡");
            System.out.println("通知时间:" + System.currentTimeMillis() + " -- 当前线程:" + Thread.currentThread().getName());
            try {
                washCondition.signalAll();
            } finally {
                lock.unlock();
            }
        }
    
    }
    
    

    ②线程类

    package com.example.demo.practice;
    
    public class WashThreadA implements Runnable {
    
        private RobotService robotService;
    
        public WashThreadA(RobotService robotService) {
            this.robotService = robotService;
        }
    
        @Override
        public void run() {
            robotService.awaitCuoZao();
        }
    
    }
    
    package com.example.demo.practice;
    
    public class WashThreadB implements Runnable {
    
        private RobotService robotService;
    
        public WashThreadB(RobotService robotService) {
            this.robotService = robotService;
        }
    
        @Override
        public void run() {
            robotService.awaitMuyulu();
        }
    
    }
    
    package com.example.demo.practice;
    
    public class WashThreadC implements Runnable {
    
        private RobotService robotService;
    
        public WashThreadC(RobotService robotService) {
            this.robotService = robotService;
        }
    
        @Override
        public void run() {
            robotService.awaitChuanyi();
        }
    
    }
    
    

    ③测试类

    package com.example.demo.practice;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class ReenTrantLockTest {
    
        public static void main(String[] args) throws InterruptedException {
    
            RobotService robotService = new RobotService();
    
            System.out.println("老板:我想洗澡,去准备一下。");
    
            WashThreadA washThreadA = new WashThreadA(robotService);
            Thread czReady = new Thread(washThreadA);
            czReady.setName("czReady");
            czReady.start();
    
            Thread.sleep(500);
    
            WashThreadB washThreadB = new WashThreadB(robotService);
            Thread myReady = new Thread(washThreadB);
            myReady.setName("myReady");
            myReady.start();
    
            Thread.sleep(500);
    
            WashThreadC washThreadC = new WashThreadC(robotService);
            Thread gyReady = new Thread(washThreadC);
            gyReady.setName("gyReady");
            gyReady.start();
    
            Thread.sleep(2000);
    
            robotService.signalWash();
    
        }
    }
    
    

    ④控制台打印

    老板:我想洗澡,去准备一下。
    等着给老板搓澡...
    开始等待时间:1559033214928 -- 当前线程:czReady
    等着给老板打沐浴露...
    开始等待时间:1559033215425 -- 当前线程:myReady
    等着给老板更衣...
    开始等待时间:1559033215926 -- 当前线程:gyReady
    老板:给我洗澡
    通知时间:1559033217926 -- 当前线程:main
    结束等待时间:1559033217926 -- 当前线程:czReady
    搓澡完毕!
    结束等待时间:1559033220928 -- 当前线程:myReady
    打沐浴露完毕!
    结束等待时间:1559033223928 -- 当前线程:gyReady
    更衣完毕!
    

    代码地址:https://github.com/hardworkingman/take-a-bath

    相关文章

      网友评论

          本文标题:ReentrantLock的Condition选择性通知

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