Code review comment: Yea the sleep is for making sure the thread is started. I've updated the test to wait for a notifcation on thread start for each workitem.

Code before review:
public void testActiveThreadMetric() throws Exception {
int maxThreads = 5;
int threadExpiration = 60;
BoundedQueueExecutor executor =
new BoundedQueueExecutor(
maxThreads,
threadExpiration,
TimeUnit.SECONDS,
maxThreads,
10000000,
new ThreadFactoryBuilder()
.setNameFormat("DataflowWorkUnits-%d")
.setDaemon(true)
.build());
StreamingDataflowWorker.ComputationState computationState =
new StreamingDataflowWorker.ComputationState(
"computation",
defaultMapTask(Arrays.asList(makeSourceInstruction(StringUtf8Coder.of()))),
executor,
ImmutableMap.of(),
null);
ShardedKey key1Shard1 = ShardedKey.create(ByteString.copyFromUtf8("key1"), 1);
MockActiveWork m1 =
new MockActiveWork(1) {
@Override
public void run() {
int count = 0;
while (!exit) {
count += 1;
}
Thread.currentThread().interrupt();
}
};
MockWork m2 =
new MockWork(2) {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
MockWork m3 =
new MockWork(3) {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
assertEquals(0, executor.activeCount());
assertTrue(computationState.activateWork(key1Shard1, m1));
executor.execute(m1, m1.getWorkItem().getSerializedSize());
Thread.sleep(1000);
assertEquals(2, executor.activeCount());
assertTrue(computationState.activateWork(key1Shard1, m2));
assertTrue(computationState.activateWork(key1Shard1, m3));
executor.execute(m2, m2.getWorkItem().getSerializedSize());
executor.execute(m3, m3.getWorkItem().getSerializedSize());
Thread.sleep(1000);
assertEquals(4, executor.activeCount());
m1.stop();
executor.shutdown();
}

Line under review: Thread.sleep(1000);

Code after addressing the review:
public void testActiveThreadMetric() throws Exception {
int maxThreads = 5;
int threadExpirationSec = 60;
BoundedQueueExecutor executor =
new BoundedQueueExecutor(
maxThreads,
threadExpirationSec,
TimeUnit.SECONDS,
maxThreads,
10000000,
new ThreadFactoryBuilder()
.setNameFormat("DataflowWorkUnits-%d")
.setDaemon(true)
.build());
ComputationState computationState =
new ComputationState(
"computation",
defaultMapTask(Arrays.asList(makeSourceInstruction(StringUtf8Coder.of()))),
executor,
ImmutableMap.of(),
null);
ShardedKey key1Shard1 = ShardedKey.create(ByteString.copyFromUtf8("key1"), 1);
Consumer<Work> sleepProcessWorkFn =
unused -> {
synchronized (this) {
this.notify();
}
int count = 0;
while (!stop) {
count += 1;
}
};
Work m2 = createMockWork(2, sleepProcessWorkFn);
Work m3 = createMockWork(3, sleepProcessWorkFn);
Work m4 = createMockWork(4, sleepProcessWorkFn);
assertEquals(0, executor.activeCount());
assertTrue(computationState.activateWork(key1Shard1, m2));
synchronized (this) {
executor.execute(m2, m2.getWorkItem().getSerializedSize());
this.wait();
this.wait();
}
assertEquals(2, executor.activeCount());
assertTrue(computationState.activateWork(key1Shard1, m3));
assertTrue(computationState.activateWork(key1Shard1, m4));
synchronized (this) {
executor.execute(m3, m3.getWorkItem().getSerializedSize());
this.wait();
}
assertEquals(3, executor.activeCount());
synchronized (this) {
executor.execute(m4, m4.getWorkItem().getSerializedSize());
this.wait();
}
assertEquals(4, executor.activeCount());
stop = true;
executor.shutdown();
}