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既保证线程安全性,也大大增强了并发时的效率(跟并发锁方式相比).尤其当一个 ...
随机推荐
- ng-strict-di
关于AngularJS中的ng-strict-di: 首先我们要知道"注入"的概念: 在Angular中,如果想使用模块中的内容,只需要提供它的名称即可,不需自己查找.创建.初始化 ...
- [原]在AMD机器上使用android studio
amd机器上使用android studio进行调试.因为amd的cpu不支持IntelVT,所以可能会有如下错误提示 我们有几个选择: 1. 使用真机调试 2. 配合genymotion 3. ...
- python 学习笔记十七 django深入学习二 form,models
表单 GET 和 POST 处理表单时候只会用到GET 和 POST 方法. Django 的登录表单使用POST 方法,在这个方法中浏览器组合表单数据.对它们进行编码以用于传输.将它们发送到服务器然 ...
- 【Spring】简单的Spring MVC入门例子
前言 测试特性需要搭建一个简单的Spring MVC的例子,遂记录之,只是例子,只为入门者之示例. 版本说明 声明POM文件,指定需引入的JAR. <properties> <spr ...
- tomcat部署web项目的3中方法
1.直接把项目复制到Tomcat安装目录的webapps目录中,这是最简单的一种Tomcat项目部署的方法,也是初学者最常用的方法. 2.在tomcat安装目录中有一个conf文件夹,打开此文件夹,其 ...
- SQL2008 的 日期数据类型
摘要 你是否曾经想在数据库中存储一个日期而没有时间部分,或者想存储一个时间值希望有更高的精度?在SQL Server 2008的介绍中,微软介绍了一些新的日期数据类允许你只存储一个日期.更高精度的时间 ...
- c# 无法加载 DLL xxxxxxxx找不到指定的模块。 (异常来自HRESULT:0x8007007E)。的一个解决方法
最近在做一个程序,想把某些功能用C++写成DLL供C#调用.但是无法如何都无法调用,提示"无法加载 DLL xxxxxxxx找不到指定的模块. (异常来自HRESULT:0x8007007E ...
- AspNet MVC中各种上下文理解
0 前言 AspNet MVC中比较重要的上下文,有如下: 核心的上下文有HttpContext(请求上下文),ControllerContext(控制器上下文) 过滤器有关有五个的上下文Actio ...
- Linux C相关基础
系统求助 man 函数名 man 2 函数名 - 表示函数是系统调用函数 man 3 函数名 - 表示函数是C的库函数 eg:man fread man 2 w ...
- 基础笔记12(socket,url网络通信)
进一步深入socket 1.网络通信条件: .IP地址,可用主机名. .传输数据时将不用的应用程序通过数字标识区分开来,这种标识称为逻辑端口,也称端口.(0-65535端口,一般系统预留0-1024) ...