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.
1 +package org.onlab.util;
2 +
3 +import java.util.concurrent.Callable;
4 +import java.util.concurrent.CountDownLatch;
5 +import java.util.concurrent.ExecutorService;
6 +import java.util.concurrent.TimeUnit;
7 +import java.util.concurrent.atomic.AtomicReference;
8 +
9 +import org.junit.After;
10 +import org.junit.Before;
11 +import org.junit.Test;
12 +import org.onlab.util.PredictableExecutor.PickyRunnable;
13 +import com.google.common.testing.EqualsTester;
14 +
15 +public class PredictableExecutorTest {
16 +
17 + private PredictableExecutor pexecutor;
18 + private ExecutorService executor;
19 +
20 + @Before
21 + public void setUp() {
22 + pexecutor = new PredictableExecutor(3, Tools.namedThreads("Thread-%d"));
23 + executor = pexecutor;
24 + }
25 +
26 + @After
27 + public void tearDown() {
28 + pexecutor.shutdownNow();
29 + }
30 +
31 + @Test
32 + public void test() throws InterruptedException {
33 + CountDownLatch latch = new CountDownLatch(7);
34 + AtomicReference<String> hintValue0 = new AtomicReference<>("");
35 + AtomicReference<String> hintValue1 = new AtomicReference<>("");
36 + AtomicReference<String> hintFunction0 = new AtomicReference<>("");
37 + AtomicReference<String> pickyRunnable0 = new AtomicReference<>("");
38 + AtomicReference<String> pickyRunnable1 = new AtomicReference<>("");
39 + AtomicReference<String> pickyCallable0 = new AtomicReference<>("");
40 + AtomicReference<String> hashCode0 = new AtomicReference<>("");
41 +
42 + pexecutor.execute(() -> {
43 + hintValue0.set(Thread.currentThread().getName());
44 + latch.countDown();
45 + }, 0);
46 +
47 + pexecutor.execute(() -> {
48 + hintValue1.set(Thread.currentThread().getName());
49 + latch.countDown();
50 + }, 1);
51 +
52 + pexecutor.execute(() -> {
53 + hintFunction0.set(Thread.currentThread().getName());
54 + latch.countDown();
55 + }, (runnable) -> 0);
56 +
57 + pexecutor.execute(new PickyRunnable() {
58 +
59 + @Override
60 + public void run() {
61 + pickyRunnable0.set(Thread.currentThread().getName());
62 + latch.countDown();
63 + }
64 +
65 + @Override
66 + public int hint() {
67 + return 0;
68 + }
69 + });
70 +
71 + executor.execute(new PickyRunnable() {
72 +
73 + @Override
74 + public void run() {
75 + pickyRunnable1.set(Thread.currentThread().getName());
76 + latch.countDown();
77 + }
78 +
79 + @Override
80 + public int hint() {
81 + return 1;
82 + }
83 + });
84 +
85 + Callable<Void> callable = new Callable<Void>() {
86 + @Override
87 + public Void call() {
88 + pickyCallable0.set(Thread.currentThread().getName());
89 + latch.countDown();
90 + return null;
91 + }
92 + };
93 +
94 + executor.submit(PredictableExecutor.picky(callable, 0));
95 +
96 +
97 + executor.execute(new Runnable() {
98 +
99 + @Override
100 + public void run() {
101 + hashCode0.set(Thread.currentThread().getName());
102 + latch.countDown();
103 +
104 + }
105 +
106 + @Override
107 + public int hashCode() {
108 + return 0;
109 + }
110 + });
111 +
112 + latch.await(1, TimeUnit.SECONDS);
113 +
114 + new EqualsTester()
115 + .addEqualityGroup(hintValue0.get(),
116 + hintFunction0.get(),
117 + pickyRunnable0.get(),
118 + pickyCallable0.get(),
119 + hashCode0.get())
120 + .addEqualityGroup(hintValue1.get(),
121 + pickyRunnable1.get())
122 + .testEquals();
123 + }
124 +}