guava学习--monitor
转载:https://my.oschina.net/realfighter/blog/349924
https://my.oschina.net/realfighter/blog/349926
Monitor类是作为ReentrantLock的一个替代,代码中使用 Monitor比使用ReentrantLock更不易出错,可读性也更强,并且也没有显著的性能损失,使用Monitor甚至有潜在的性能得到优化。
public abstract static class Guard:一个标识线程是否等待的布尔条件,Guard类总是与单一的Monitor相关联,Monitor可以在任意时间从任意占用Monitor的线程检查Guard,这样代码的编写将不在关心Guard是否被检查的频率。
public abstract boolean isSatisfied():Guard内部提供的抽象方法,isSatisfied(),当被关联的Monitor被占用时,Guard的此方法会被调用,该方法的实现必须取决于被关联Monitor保护的状态,并且状态不可修改。
Monitor有几个常用的方法
- enter():进入到当前Monitor,无限期阻塞,等待锁。(这里没有Guard)
- enter(long time, TimeUnit unit):进入到当前Monitor,最多阻塞给定的时间,返回是否进入Monitor。
- tryEnter():如果可以的话立即进入Monitor,不阻塞,返回是否进入Monitor。
- enterWhen(Guard guard):进入当前Monitor,等待Guard的isSatisfied()为true后,继续往下执行 ,但可能会被打断; 为false,会阻塞。
- enterIf(Guard guard):如果Guard的isSatisfied()为true,进入当前Monitor。等待获得锁(这里会等待获取锁),不需要等待Guard satisfied。
- tryEnterIf(Guard guard):如果Guard的isSatisfied()为true并且可以的话立即进入Monitor,不等待获取锁(这里不等待获取锁),也不等待Guard satisfied。
- 感觉 enterWhen enterIf的用的区别就是前者无返回值,后者返回Boolean值。
import com.google.common.util.concurrent.Monitor;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 原文地址:https://gist.github.com/bbejeck/1369371
* User: bbejeck
*/
public class MonitorExample {
private final Monitor monitor = new Monitor();
private volatile boolean condition = true;
private int taskDoneCounter;
//AtomicInteger:线程安全的加减操作
private AtomicInteger taskSkippedCounter = new AtomicInteger(0);
private int stopTaskCount;
private Monitor.Guard conditionGuard = new Monitor.Guard(monitor) {
@Override
public boolean isSatisfied() {
return condition;
}
};
public void demoTryEnterIf() throws InterruptedException {
if (monitor.tryEnterIf(conditionGuard)) {
try {
simulatedWork();
taskDoneCounter++;
} finally {
monitor.leave();
}
} else {
//自增加1
taskSkippedCounter.incrementAndGet();
}
}
public void demoEnterIf() throws InterruptedException {
if (monitor.enterIf(conditionGuard)) {
try {
taskDoneCounter++;
if (taskDoneCounter == stopTaskCount) {
condition = false;
}
} finally {
monitor.leave();
}
} else {
taskSkippedCounter.incrementAndGet();
}
}
public void demoEnterWhen() throws InterruptedException {
monitor.enterWhen(conditionGuard);
try {
taskDoneCounter++;
if (taskDoneCounter == stopTaskCount) {
condition = false;
}
} finally {
monitor.leave();
}
}
private void simulatedWork() throws InterruptedException {
Thread.sleep(250);
}
// public void reEvaluateGuardCondition() {
// monitor.reevaluateGuards();
// }
public int getStopTaskCount() {
return stopTaskCount;
}
public void setStopTaskCount(int stopTaskCount) {
this.stopTaskCount = stopTaskCount;
}
public void setCondition(boolean condition) {
this.condition = condition;
}
public int getTaskSkippedCounter() {
return taskSkippedCounter.get();
}
public int getTaskDoneCounter() {
return taskDoneCounter;
}
}
Test类:
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.concurrent.*;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* 原文地址:https://gist.github.com/bbejeck/1369371
* User: bbejeck
*/
public class MonitorExampleTest {
private MonitorExample monitorExample;
private ExecutorService executorService;
private int numberThreads = 10;
// CountDownLatch:同步辅助类,允许一个或多个线程等待其他线程所执行的一组操作完成
private CountDownLatch startSignal;
private CountDownLatch doneSignal;
@Before
public void setUp() throws Exception {
monitorExample = new MonitorExample();
executorService = Executors.newFixedThreadPool(numberThreads);
startSignal = new CountDownLatch(1);
doneSignal = new CountDownLatch(numberThreads);
}
@After
public void tearDown() {
executorService.shutdownNow();
}
/**
* 第一个线程会进入Monitor调用simulatedWork()后线程等待
* 其余9个线程则会进入else,对taskSkippedCounter自增
*
* @throws Exception
*/
@Test
public void testDemoTryEnterIf() throws Exception {
setUpThreadsForTestingMethod("demoTryEnterIf");
startAllThreadsForTest();
waitForTestThreadsToFinish();
int expectedTaskCount = 1;
int expectedSkippedTasks = 9;
assertThat(monitorExample.getTaskDoneCounter(), is(expectedTaskCount));
assertThat(monitorExample.getTaskSkippedCounter(), is(expectedSkippedTasks));
}
/**
* 前5个线程会等待Monitor,因为Guard的isSatisfied()为true
* 但是一旦isSatisfied()变为false,剩余的线程会进入else,
* 对taskSkippedCounter自增
*
* @throws Exception
*/
@Test
public void testDemoEnterIfOnlyFiveTasksComplete() throws Exception {
monitorExample.setStopTaskCount(5);
setUpThreadsForTestingMethod("demoEnterIf");
startAllThreadsForTest();
waitForTestThreadsToFinish();
int expectedTaskCount = 5;
int expectedSkippedTasks = 5;
assertThat(monitorExample.getTaskDoneCounter(), is(expectedTaskCount));
assertThat(monitorExample.getTaskSkippedCounter(), is(expectedSkippedTasks));
}
/**
* 所有10个线程都会进入Monitor,因为在整个时间内Guard的isSatisfied()为true
*
* @throws Exception
*/
@Test
public void testDemoEnterIfAllTasksComplete() throws Exception {
monitorExample.setStopTaskCount(Integer.MAX_VALUE);
setUpThreadsForTestingMethod("demoEnterIf");
startAllThreadsForTest();
waitForTestThreadsToFinish();
int expectedTaskCount = 10;
int expectedSkippedTasks = 0;
assertThat(monitorExample.getTaskDoneCounter(), is(expectedTaskCount));
assertThat(monitorExample.getTaskSkippedCounter(), is(expectedSkippedTasks));
}
/**
* Guard的isSatisfied()初始化为true,但是所有10个线程会进入Monitor
*
* @throws Exception
*/
@Test
public void testDemoEnterWhen() throws Exception {
monitorExample.setStopTaskCount(Integer.MAX_VALUE);
monitorExample.setCondition(false);
setUpThreadsForTestingMethod("demoEnterWhen");
startAllThreadsForTest();
int expectedCompletedCount = 0;
int completedCount = monitorExample.getTaskDoneCounter();
assertThat(completedCount, is(expectedCompletedCount));
monitorExample.setCondition(true);
waitForTestThreadsToFinish();
expectedCompletedCount = 10;
completedCount = monitorExample.getTaskDoneCounter();
assertThat(completedCount, is(expectedCompletedCount));
}
/**
* 在3个线程完成工作后,人为的设置Guard的isSatisfied()为false
* 以证明剩余的7个线程将等待,直到isSatisfied()变为true
* 然后才会进入Monitor.
*
* @throws Exception
*/
@Test
public void testDemoEnterWhenAllTasksCompleteEvenWhenConditionChanges() throws Exception {
monitorExample.setCondition(true);
monitorExample.setStopTaskCount(3);
setUpThreadsForTestingMethod("demoEnterWhen");
startAllThreadsForTest();
//验证最初只有3个线程工作, 重新设定Guard的isSatisfied()为true
FutureTask<Integer> checkInitialTasksCompleted = new FutureTask<Integer>(
new Callable<Integer>() {
public Integer call() {
int initialCompletedTasks = monitorExample.getTaskDoneCounter();
monitorExample.setCondition(true);
// monitorExample.reEvaluateGuardCondition();
return initialCompletedTasks;
}
});
new Thread(checkInitialTasksCompleted).start();
int expectedCompletedCount = 3;
int completedCount = checkInitialTasksCompleted.get();
assertThat(completedCount, is(expectedCompletedCount));
waitForTestThreadsToFinish();
assertThat(completedCount, is(expectedCompletedCount));
expectedCompletedCount = 10;
completedCount = monitorExample.getTaskDoneCounter();
assertThat(completedCount, is(expectedCompletedCount));
}
private void waitForTestThreadsToFinish() throws InterruptedException {
doneSignal.await(1000l, TimeUnit.MILLISECONDS);
}
private void startAllThreadsForTest() {
startSignal.countDown();
}
private Method getMethodUnderTest(String methodName) throws Exception {
return monitorExample.getClass().getDeclaredMethod(methodName);
}
private void setUpThreadsForTestingMethod(String methodName) throws Exception {
final Method testMethod = getMethodUnderTest(methodName);
for (int i = 0; i < numberThreads; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
try {
startSignal.await();
testMethod.invoke(monitorExample);
} catch (Exception e) {
//异常无须处理
} finally {
doneSignal.countDown();
}
}
});
}
}
}
guava学习--monitor的更多相关文章
- Guava学习笔记目录
Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libra ...
- guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁
guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁 1,本文翻译自 http://eclipsesource.com/blogs/2012/06/06/cleaner-code- ...
- guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用
guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用 1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: Introduction Guava Collection ...
- Guava学习
Guava学习笔记目录 Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concu ...
- [置顶] Guava学习之ArrayListMultimap
ArrayListMultimap类的继承关系如下图所示: Guava ArrayListMultimap List Multimap 是一个接口,继承自 Multimap 接口.ListMultim ...
- [置顶] Guava学习之Splitter
Splitter:在Guava官方的解释为:Extracts non-overlapping substrings from an input string, typically by recogni ...
- [置顶] Guava学习之Iterators
Iterators类提供了返回Iterator类型的对象或者对Iterator类型对象操作的方法.除了特别的说明,Iterators类中所有的方法都在Iterables类中有相应的基于Iterable ...
- [置顶] Guava学习之Lists
Lists类主要提供了对List类的子类构造以及操作的静态方法.在Lists类中支持构造ArrayList.LinkedList以及newCopyOnWriteArrayList对象的方法.其中提供了 ...
- [置顶] Guava学习之Immutable集合
Immutable中文意思就是不可变.那为什么需要构建一个不可变的对象?原因有以下几点: 在并发程序中,使用Immutable既保证线程安全性,也大大增强了并发时的效率(跟并发锁方式相比).尤其当一个 ...
随机推荐
- HTML5的新增方法
json的新增方法: parse() 将JSON转换为字符串:必须是严格的JSON格式: 用法 : var s = {"name":"name"}; JSO ...
- PHP是弱类型语言,自动转换,强制转换
强制转换: (int) - 转换成整型 (bool) - 转换.成布尔型 (float) - 转换成浮点型 (string) - 转换成字符串 (array) - 转换成数组 (object) - 转 ...
- CryptoJS DES加密
<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equ ...
- ML-分类与逻辑回归
布尔分类(binary classification)问题: 训练集:$S=\{(x^{(i)}, y^{(i)})\}$ 输入:特征向量$x$ 期望输出:$y\in\{0, 1\}$ 这里使用的假设 ...
- [转]RAID基础,RAID10与RAID01比较,RAID10与RAID5比较
原文:http://blog.itpub.net/787018/viewspace-666280/ 文档内容3部分:1.基本的RAID级别介绍2.RAID10和RAID01的比较3.RAID10和RA ...
- -[NSBundle initWithURL:]: nil URL argument'
今天早上同事突然跟我说趣拍的SDK不能用了,一调用就crash,我一听就纳了闷了,原来好好的啊. 然后就开始查呗,马上就要上线了,不搞好,老大会不会杀了我... 搞个全局断点,就停在了一堆我看不懂的界 ...
- HDU 5860 Death Sequence(死亡序列)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- validate插件深入学习-01 小白从看透一个插件开始
没有编程基础的的我,即使看了一遍jq文档也不知道怎么写程序,一个新的插件看了也不知道怎么用. 总是想做自己会的,自己不会的永远不去触碰,就永远不会. 都说编程这东西,很多都有很像的地方了,一个语言学通 ...
- java简单计算器
写的一个小计算器,留着以后看吧. import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import ...
- 给博客添加Flash时钟
依稀记得在cnblogs很多大牛的博客里见到过大牛的新闻公告栏里那种动感十足的Flash时钟控件,先上图: 作为一名刚的接触博客菜鸟,自然免不了一番好奇.博客设置选项里翻来覆去找(以为是cnblogs ...