package org.infinispan.executors; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.infinispan.test.AbstractInfinispanTest; import org.infinispan.util.concurrent.BlockingRunnable; import org.infinispan.util.concurrent.BlockingTaskAwareExecutorService; import org.infinispan.util.concurrent.BlockingTaskAwareExecutorServiceImpl; import org.testng.annotations.Test; /** * Simple executor test * * @author Pedro Ruivo * @since 5.3 */ @Test(groups = "functional", testName = "executors.BlockingTaskAwareExecutorServiceTest") public class BlockingTaskAwareExecutorServiceTest extends AbstractInfinispanTest { private static final AtomicInteger THREAD_ID = new AtomicInteger(0); public void testSimpleExecution() throws Exception { BlockingTaskAwareExecutorService executorService = createExecutorService(); try { final DoSomething doSomething = new DoSomething(); executorService.execute(doSomething); Thread.sleep(100); assert !doSomething.isReady(); assert !doSomething.isExecuted(); doSomething.markReady(); executorService.checkForReadyTasks(); assert doSomething.isReady(); eventually(doSomething::isExecuted); } finally { executorService.shutdownNow(); } } public void testMultipleExecutions() throws Exception { BlockingTaskAwareExecutorServiceImpl executorService = createExecutorService(); try { List<DoSomething> tasks = new LinkedList<>(); for (int i = 0; i < 30; ++i) { tasks.add(new DoSomething()); } tasks.forEach(executorService::execute); for (DoSomething doSomething : tasks) { assert !doSomething.isReady(); assert !doSomething.isExecuted(); } tasks.forEach(BlockingTaskAwareExecutorServiceTest.DoSomething::markReady); executorService.checkForReadyTasks(); for (final DoSomething doSomething : tasks) { eventually(doSomething::isExecuted); } } finally { executorService.shutdownNow(); } } private BlockingTaskAwareExecutorServiceImpl createExecutorService() { final String controllerName = "Controller-" + getClass().getSimpleName(); final ExecutorService realOne = new ThreadPoolExecutor(1, 2, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new DummyThreadFactory()); return new BlockingTaskAwareExecutorServiceImpl(controllerName, realOne, TIME_SERVICE); } public static class DummyThreadFactory implements ThreadFactory { @Override public Thread newThread(Runnable runnable) { return new Thread(runnable, "Remote-" + getClass().getSimpleName() + "-" + THREAD_ID.incrementAndGet()); } } public static class DoSomething implements BlockingRunnable { private volatile boolean ready = false; private volatile boolean executed = false; @Override public synchronized final boolean isReady() { return ready; } @Override public synchronized final void run() { executed = true; } public synchronized final void markReady() { ready = true; } public synchronized final boolean isExecuted() { return executed; } } }