Yuta HIGUCHI

ExecutorService with somewhat predictable thread assignment.

- ExecutorService which allows the caller or the Task to
  express hint about which Thread it needs to be executed.

Change-Id: If1cc58f6b2369bb5afce4f402c195eacedf67f05
This diff is collapsed. Click to expand it.
package org.onlab.util;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.util.PredictableExecutor.PickyRunnable;
import com.google.common.testing.EqualsTester;
public class PredictableExecutorTest {
private PredictableExecutor pexecutor;
private ExecutorService executor;
@Before
public void setUp() {
pexecutor = new PredictableExecutor(3, Tools.namedThreads("Thread-%d"));
executor = pexecutor;
}
@After
public void tearDown() {
pexecutor.shutdownNow();
}
@Test
public void test() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(7);
AtomicReference<String> hintValue0 = new AtomicReference<>("");
AtomicReference<String> hintValue1 = new AtomicReference<>("");
AtomicReference<String> hintFunction0 = new AtomicReference<>("");
AtomicReference<String> pickyRunnable0 = new AtomicReference<>("");
AtomicReference<String> pickyRunnable1 = new AtomicReference<>("");
AtomicReference<String> pickyCallable0 = new AtomicReference<>("");
AtomicReference<String> hashCode0 = new AtomicReference<>("");
pexecutor.execute(() -> {
hintValue0.set(Thread.currentThread().getName());
latch.countDown();
}, 0);
pexecutor.execute(() -> {
hintValue1.set(Thread.currentThread().getName());
latch.countDown();
}, 1);
pexecutor.execute(() -> {
hintFunction0.set(Thread.currentThread().getName());
latch.countDown();
}, (runnable) -> 0);
pexecutor.execute(new PickyRunnable() {
@Override
public void run() {
pickyRunnable0.set(Thread.currentThread().getName());
latch.countDown();
}
@Override
public int hint() {
return 0;
}
});
executor.execute(new PickyRunnable() {
@Override
public void run() {
pickyRunnable1.set(Thread.currentThread().getName());
latch.countDown();
}
@Override
public int hint() {
return 1;
}
});
Callable<Void> callable = new Callable<Void>() {
@Override
public Void call() {
pickyCallable0.set(Thread.currentThread().getName());
latch.countDown();
return null;
}
};
executor.submit(PredictableExecutor.picky(callable, 0));
executor.execute(new Runnable() {
@Override
public void run() {
hashCode0.set(Thread.currentThread().getName());
latch.countDown();
}
@Override
public int hashCode() {
return 0;
}
});
latch.await(1, TimeUnit.SECONDS);
new EqualsTester()
.addEqualityGroup(hintValue0.get(),
hintFunction0.get(),
pickyRunnable0.get(),
pickyCallable0.get(),
hashCode0.get())
.addEqualityGroup(hintValue1.get(),
pickyRunnable1.get())
.testEquals();
}
}