package com.netflix.astyanax.contrib.valve;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class MultiThreadTestControl {
// threads and thread pool
final int numThreads;
ExecutorService threadPool;
// multi-thread test control
// barrier tells all threads to wait.
final CyclicBarrier barrier;
// atomic boolean tells them to stop running
final AtomicBoolean stop = new AtomicBoolean(false);
// latch tells main test that threads have stopped running and hence successCount is not moving fwd
final CountDownLatch latch;
public MultiThreadTestControl() {
this(8);
}
public MultiThreadTestControl(int nThreads) {
numThreads = nThreads;
barrier = new CyclicBarrier(numThreads);
latch = new CountDownLatch(numThreads);
}
public void runTest(final Callable<Void> perThreadIterationCall) {
threadPool = Executors.newFixedThreadPool(numThreads);
for (int i=0; i<numThreads; i++) {
threadPool.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
barrier.await();
while (!stop.get()) {
perThreadIterationCall.call();
}
// stopping test thread
latch.countDown();
return null;
}
});
}
}
public void stopTest() {
stop.set(true);
threadPool.shutdownNow();
try {
latch.await(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}