并发工具:Guava之Monitor

1 Monitor介绍

无论使用对象监视器的wait notify/notifyAll还是Condition的await signal/ signalAll方法调用,我们首先都会对共享数据的临界值进行判断,当条件满足或者不满足的时候才会调用相关方法使得当前线程挂起,或者唤醒wait队列/set中的线程,因此对共享数据临界值的判断非常关键,Guava的Monitor工具提供了一种将临界值判断抽取成Guard的处理方式,可以很方便地定义若干个Guard也就是临界值的判断,以及对临界值判断的重复使用,除此之外Monitor还具备synchronized关键字和显式锁Lock的完整语义

2 入门案例

public class MonitorExample1 {

    /**
     * 定义Monitor对象
     */
    private static Monitor monitor = new Monitor();

    /**
     * 共享数据,一个简单的int类型数据
     */
    private static int x = 0;

    /**
     * 定义临界值,共享数据的值不能超过MAX_VALUE
     */
    private static final int MAX_VALUE = 10;


    /**
     * 定义Guard 并且实现isSatisfied方法
     */
    private static final Monitor.Guard INC_WHEN_LESS_10 = new Monitor.Guard(monitor) {

        /**
         * 该方法就相当于我们在写对象监视器或者Condition时的临界值判断逻辑
         * @return
         */
        @Override
        public boolean isSatisfied() {
            return x < MAX_VALUE;
        }
    };

    public static void main(String[] args) throws InterruptedException {
        while (true) {
            monitor.enterWhen(INC_WHEN_LESS_10);
            try {
                x++;
                System.out.println(currentThread().getName() + ": x value is: " + x);
            }finally {
                monitor.leave();
            }
        }
    }
}
  1. 我们首先定义了一个Monitor对象,接着又将临界值的判断抽取成了Guard,我们只需要将临界值的判断逻辑写在isSatisfied()方法中即可,当共享数据的值大于10的时候无法对其再次进行自增操作。
  2. 在main方法中(main线程中),我们采取无限循环的方式对共享数据x进行自增操作
  3. 对x进行操作之前先调用monitor.enterWhen()方法,该方法除了具备锁的功能之外还具备临界值判断的操作,因此只有当x满足临界值判断时当前线程才会对x进行自增运算,否则当前线程将会进入阻塞队列(其实在Guard内部使用的也是Condition)
  4. 对x的运算成功之后,调用leave()方法,该方法除了释放当前的锁之外,还会通知唤醒与Guard关联的Condition阻塞队列中的某个阻塞线程。

运行上面的代码,我们会发现临界值条件不满足时,当前线程(main线程)将会进入阻塞状态:

main: x value is: 1
main: x value is: 2
main: x value is: 3
main: x value is: 4
main: x value is: 5
main: x value is: 6
main: x value is: 7
main: x value is: 8
main: x value is: 9
main: x value is: 10

当某个线程进入Monitor代码块时,实际上它首先要抢占与Monitor关联的Lock,当该线程调用了leave方法,实际上是需要释放与Monitor关联的Lock,因此在某个时刻仅有一个线程能够进入到Monitor代码块中(排他的)

3 Monitor的其他方法

enter():该方法完全等价于Lock的lock()方法。

enterIf(Guard guard):该方法主要用于判断当前的Guard是否满足临界值的判断,也是使用比较多的一个操作,调用该方法,当前线程并不会进入阻塞之中。

tryEnter():等价于Lock的tryLock()方法。

waitFor(Guard guard):当前线程将会阻塞等待,直到Guard的条件满足当前线程才会退出阻塞状态。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值