235. Using Semaphore instead of Executor
Let’s say that we have the following task (Runnable):
Runnable task = () -> {
  try {
    Thread.sleep(5000);
  } catch (InterruptedException ex) { /* handle exception */ }
  logger.info(Thread.currentThread().toString());
};
And we plan to execute this task 15 times by 3 threads:
private static final int NUMBER_OF_TASKS = 15;
private static final int NUMBER_OF_THREADS = 3;
We can easily solve this problem via Executors.newFixedThreadPool() and platform threads:
// using cached platform threads
try (ExecutorService executor = 
  Executors.newFixedThreadPool(NUMBER_OF_THREADS)) {
  for (int i = 0; i < NUMBER_OF_TASKS; i++) {
    executor.submit(task);
  }
}
A snippet of the possible output:
Thread[#24,pool-1-thread-3,5,main] 
Thread[#22,pool-1-thread-1,5,main] 
Thread[#23,pool-1-thread-2,5,main] 
Thread[#22,pool-1-thread-1,5,main] 
Thread[#24,pool-1-thread-3,5,main] 
Thread[#23,pool-1-thread-2,5,main... 
                                             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
             
     
         
                 
                 
                 
                 
                 
                 
                 
                 
                