This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LazyInitService implements Service { | |
private Service service; | |
@Override | |
public LocalDateTime getTime() { | |
initializeIfNecessary(); | |
return service.getTime(); | |
} | |
private void initializeIfNecessary() { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Test | |
public void shouldHaveZeroThreadsAtTheBeginning() { | |
int activeThreads = dynamicThreadPool.threadsCount(); | |
assertThat(activeThreads).isEqualTo(0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public Future<T> submitTask(Callable<T> task); | |
public int threadsCount(); |