Skip to content

Instantly share code, notes, and snippets.

public class LazyInitService implements Service {
private Service service;
@Override
public LocalDateTime getTime() {
initializeIfNecessary();
return service.getTime();
}
private void initializeIfNecessary() {
public interface Service {
LocalDateTime getTime();
}
public class DefaultService implements Service {
private static final Logger logger = LoggerFactory.getLogger(DefaultService.class.getName());
public DefaultService() {
logger.debug("Initializing service");
}
public class DynamicThreadPool<T> {
private final ThreadPoolExecutor executor;
public DynamicThreadPool(int maxThreads, int keepAliveTimeInMillis) {
executor = new ThreadPoolExecutor(0, maxThreads, keepAliveTimeInMillis, MILLISECONDS, new SynchronousQueue<>());
executor.setRejectedExecutionHandler((r, theExecutor) -> {
try {
theExecutor.getQueue().put(r);
} catch (InterruptedException e) {
private static final int MAX_THREADS = 2;
private static final int KEEP_ALIVE_TIME_IN_MILLISECONDS = 300;
private static final long DELAY_TIME_IN_MILLISECONDS = 50;
private DynamicThreadPool<String> dynamicThreadPool
= new DynamicThreadPool<>(MAX_THREADS, KEEP_ALIVE_TIME_IN_MILLISECONDS);
private static final Callable<String> TASK_WITH_DELAY = () -> {
simulateDelay(DELAY_TIME_IN_MILLISECONDS);
return randomUUID().toString();
};
@Test
public void shouldBlockAddingTasksWhenMaxThreadsCountExceeded() throws Exception {
dynamicThreadPool.submitTask(TASK_WITH_DELAY);
dynamicThreadPool.submitTask(TASK_WITH_DELAY);
long startTime = System.currentTimeMillis();
Future<String> lastTaskFuture = dynamicThreadPool.submitTask(TASK_WITH_DELAY);
String result = lastTaskFuture.get();
long timeElapsed = System.currentTimeMillis() - startTime;
assertThat(timeElapsed).isGreaterThan(DELAY_TIME_IN_MILLISECONDS);
@Test
public void shouldHaveZeroThreadsWhenNoActiveTasks() {
dynamicThreadPool.submitTask(() -> randomUUID().toString());
dynamicThreadPool.submitTask(() -> randomUUID().toString());
await().atMost(KEEP_ALIVE_TIME_IN_MILLISECONDS * 2, SECONDS)
.until(() -> dynamicThreadPool.threadsCount() == 0);
}
@Test
public void shouldDynamicallyIncreaseThreadsNumber() {
dynamicThreadPool.submitTask(TASK_WITH_DELAY);
dynamicThreadPool.submitTask(TASK_WITH_DELAY);
await().atMost(KEEP_ALIVE_TIME_IN_MILLISECONDS, SECONDS)
.until(() -> dynamicThreadPool.threadsCount() == MAX_THREADS);
}
@Test
public void shouldComputeConcurrently() throws Exception {
Future<String> firstFuture = dynamicThreadPool.submitTask(TASK_WITH_DELAY);
Future<String> secondFuture = dynamicThreadPool.submitTask(TASK_WITH_DELAY);
String firstResult = firstFuture.get();
String secondResult = secondFuture.get(DELAY_TIME_IN_MILLISECONDS / 2, MILLISECONDS);
assertThat(firstResult).isNotNull();
assertThat(secondResult).isNotNull();
}
@Test
public void shouldHaveZeroThreadsAtTheBeginning() {
int activeThreads = dynamicThreadPool.threadsCount();
assertThat(activeThreads).isEqualTo(0);
}
public Future<T> submitTask(Callable<T> task);
public int threadsCount();