Guava库学习:学习Concurrency(二)Monitor_2

    链接地址:http://www.xx566.com/detail/154.html

    上一篇Guava库学习:学习Concurrency(二)Monitor_1中,我们简单的介绍了一下Guava Concurrency Monitor监控类,并对Monitor的源码结构进行了分析,对Monitor中的一些重要的方法做了简单的整理,那么在实际的工作中我们又该怎样去应用Monitor呢?接下来,我们首先通过分析GitHub上面的开源代码,来继续进行Guava Concurrency Monitor的学习。

 

    下面的开源代码:包含Monitor的实例代码MonitorExample和对应的测试类MonitorExampleTest,由于针对的是Guava较早的版本,所以其中的一些API已经舍弃,不过仍然具有很高的学习价值,代码如下:

package guava;
 
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;
    }
}
package guava;
 
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,concurrency)