240
It works on my machine

Guava monitor

Guava的com.google.util.concurrent类库提供了相对于jdk java.util.concurrent包更加方便实用的并发类,Monitor类就是其中一个。Monitor类在处理互斥操作,同步访问数据块,提供了相比于synchronized关键字更加方便简洁的解决方案。

Synchronizing threads

Java提供了synchronized关键字来完成顺序访问某一数据块,但是使用synchronized存在一些问题,第一:如果我们使用在线程中使用wait(),我们必须记着使用while循环:

while (some condition) {
    try {
        wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

第二:如果包含多个condition可以导致一个wait状态,我们必须使用notifyAll,因为我们无法去指定的notify某个condition。使用notifyAll不尽人意,因为我们不得不去为了lock某个条件而唤醒所有的线程。Java 5引入了ReentrantLock,允许用户创建condition,可以通过使用Condition.signal()方法唤醒某一指定的condition,但是Condition.signalAll和notifyAll具有相同问题。也依然会存在while循环:

while (some condition) {
    try {
        condition.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Monitor

Monitor类允许多个conditions,可以提供隐式的线程condition转换策略。下面是一个Monitor简单的例子:

public class SerialPrinterUsingGuava {
    private static final int MAX_SIZE = 10;
    private List<String> list = new ArrayList<String>();
    private Monitor monitor = new Monitor();

    private Guard listBelowCapacity = new Guard(monitor) {
                @Override
                public boolean isSatisfied() {
                    return list.size() < MAX_SIZE;
                }
            };

    public void addToList(String item) throws InterruptedException {
        monitor.enterWhen(listBelowCapacity);
        try {
            list.add(item);
        } finally {
            monitor.leave();
        }
    }
}

上面的例子中,当调用addToList方法向list中插入数据,进入monitor块,如果满足当前定义的限制条件,list.size<MaxSize,则执行list添加数据操作,最后在finally块中会释放当前线程占有的锁。monitor.enterwhen()方法的内部实际上使用是可重入锁,当定义的Guard条件满足时,整个Monitor块会被lock,在同一个时间只允许一个线程访问monitor代码块。

Monitor最佳实践

对于Monitor方法返回Boolean值,可以使用下面的代码模板,在If中包裹try-finally,在finally中释放锁。

if(monitor.enterIf(guardCondition){
    try {
        doWork();
    } finally {
        monitor.leave();
    }
}

对于Monitor方法无返回值的,可以使用try-finally block,在finally中释放锁

monitor.enterWhen(guardCondition);
try {
    doWork();
} finally {
    monitor.leave()
}

Conclusion

今天和分享了Guava Monitor的一些特性,及其使用方法,更多的使用特性读者可以参考Google提供的Guava API文档自行查阅。

posted @ 2015-10-12 20:50  禾码大叔  阅读(1490)  评论(1编辑  收藏  举报