Could anyone explain me why CountDownLatch
on method await is hanging up although I execute countDown in separated thread? This test never ends and what is interesting ThreadPoolTaskExecutor
doesn't execute code where I want to execute countDown method. I was sure that ThreadPoolTaskExecutor
executes callback in different thread and CountDownLatch::await
will be released.
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
...
private ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
@Test
void nestedInitialization() {
executor.initialize();
var beanInitializer = new Initializer(executor);
beanInitializer.initialize(() -> {
new SomeBean().init();
});
sleep(150);
assertEquals(0, executor.getThreadPoolExecutor().getQueue().size());
assertTrue(beanInitializer.isInitializationDone());
}
class SomeBean {
private AnotherBean anotherBean = new AnotherBean();
void init() {
anotherBean.init();
}
}
class AnotherBean {
private final Initializer initializer = new Initializer(executor);
void init() {
initializer.initialize(this::internalInit);
}
void internalInit() {
sleep(100);
}
}
public class Initializer {
private ThreadPoolTaskExecutor bootstrapExecutor;
private final CountDownLatch countDownLatch = new CountDownLatch(2);
private Initializer(ThreadPoolTaskExecutor bootstrapExecutor) {
this.bootstrapExecutor = bootstrapExecutor;
}
public void initialize(Runnable callback) {
synchronized (this) {
if (isNotInitialized()) {
countDownLatch.countDown(); // set 1 in latch
bootstrapExecutor.execute(() -> {
callback.run();
countDownLatch.countDown(); // <-- this doesn't execute
});
}
}
if (initializationStarted()) {
try {
countDownLatch.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
boolean isNotInitialized() { return countDownLatch.getCount() == 2; }
boolean initializationStarted() { return countDownLatch.getCount() == 1; }
boolean isInitializationDone() { return countDownLatch.getCount() == 0; }
}
If I set any timeout in await method, callback in task executor will be executed after timeout and test passed...I can't understand this..