Category: 05. Java Concurrency

https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQrxQmP248wdHdvx2H9qVDHQPHYpqA_XNsisA&s

  • ConcurrentNavigableMap Interface

    A java.util.concurrent.ConcurrentNavigableMap interface is a subinterface of ConcurrentMap interface, and supports NavigableMap operations, and recursively so for its navigable sub-maps, and approximate matches.

    ConcurrentMap Methods

    Sr.No.Method & Description
    1NavigableSet<K> descendingKeySet()Returns a reverse order NavigableSet view of the keys contained in this map.
    2ConcurrentNavigableMap<K,V> descendingMap()Returns a reverse order view of the mappings contained in this map.
    3ConcurrentNavigableMap<K,V> headMap(K toKey)Returns a view of the portion of this map whose keys are strictly less than toKey.
    4ConcurrentNavigableMap<K,V> headMap(K toKey, boolean inclusive)Returns a view of the portion of this map whose keys are less than (or equal to, if inclusive is true) toKey.
    5NavigableSet<K> keySet()Returns a NavigableSet view of the keys contained in this map.
    6NavigableSet<K> navigableKeySet()Returns a NavigableSet view of the keys contained in this map.
    7ConcurrentNavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)Returns a view of the portion of this map whose keys range from fromKey to toKey.
    8ConcurrentNavigableMap<K,V> subMap(K fromKey, K toKey)Returns a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive.
    9ConcurrentNavigableMap<K,V> tailMap(K fromKey)Returns a view of the portion of this map whose keys are greater than or equal to fromKey.
    10ConcurrentNavigableMap<K,V> tailMap(K fromKey, boolean inclusive)Returns a view of the portion of this map whose keys are greater than (or equal to, if inclusive is true) fromKey.

    Example

    The following TestThread program shows usage of ConcurrentNavigableMap.

    import java.util.concurrent.ConcurrentNavigableMap;
    import java.util.concurrent.ConcurrentSkipListMap;
    
    public class TestThread {
    
       public static void main(final String[] arguments) {
    
      ConcurrentNavigableMap&lt;String,String&gt; map =
         new ConcurrentSkipListMap&lt;String, String&gt;();
      map.put("1", "One");
      map.put("2", "Two");
      map.put("3", "Three");
      map.put("5", "Five");
      map.put("6", "Six");
      System.out.println("Initial ConcurrentHashMap: "+map);
      System.out.println("HeadMap(\"2\") of ConcurrentHashMap: "+map.headMap("2"));
      System.out.println("TailMap(\"2\") of ConcurrentHashMap: "+map.tailMap("2"));
      System.out.println(
         "SubMap(\"2\", \"4\") of ConcurrentHashMap: "+map.subMap("2","4"));
    } }

    This will produce the following result.

    Output

    Initial ConcurrentHashMap: {1 = One, 2 = Two, 3 = Three, 5 = Five, 6 = Six}
    HeadMap("2") of ConcurrentHashMap: {1 = One}
    TailMap("2") of ConcurrentHashMap: {2 = Two, 3 = Three, 5 = Five, 6 = Six}
    SubMap("2", "4") of ConcurrentHashMap: {2 = Two, 3 = Three}
    
  • ConcurrentMap Interface

    A java.util.concurrent.ConcurrentMap interface is a subinterface of Map interface, supports atomic operations on underlying map variable. It have get and set methods that work like reads and writes on volatile variables. That is, a set has a happens-before relationship with any subsequent get on the same variable. This interface ensures thread safety and atomicity guarantees.

    ConcurrentMap Methods

    Sr.No.Method & Description
    1default V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping).
    2default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.
    3default V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)If the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value.
    4default void forEach(BiConsumer<? super K,? super V> action)Performs the given action for each entry in this map until all entries have been processed or the action throws an exception.
    5default V getOrDefault(Object key, V defaultValue)Returns the value to which the specified key is mapped, or defaultValue if this map contains no mapping for the key.
    6default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value.
    7V putIfAbsent(K key, V value)If the specified key is not already associated with a value, associate it with the given value.
    8boolean remove(Object key, Object value)Removes the entry for a key only if currently mapped to a given value.
    9V replace(K key, V value)Replaces the entry for a key only if currently mapped to some value.
    10boolean replace(K key, V oldValue, V newValue)Replaces the entry for a key only if currently mapped to a given value.
    11default void replaceAll(BiFunction<? super K,? super V,? extends V> function)Replaces each entry’s value with the result of invoking the given function on that entry until all entries have been processed or the function throws an exception.

    Example

    The following TestThread program shows usage of ConcurrentMap vs HashMap.

    import java.util.ConcurrentModificationException;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    public class TestThread {
    
       public static void main(final String[] arguments) {
    
      Map&lt;String,String&gt; map = new ConcurrentHashMap&lt;String, String&gt;();
      map.put("1", "One");
      map.put("2", "Two");
      map.put("3", "Three");
      map.put("5", "Five");
      map.put("6", "Six");
      System.out.println("Initial ConcurrentHashMap: " + map);
      Iterator&lt;String&gt; iterator = map.keySet().iterator();
      try { 
         
         while(iterator.hasNext()) {
            String key = iterator.next();
            
            if(key.equals("3")) {
               map.put("4", "Four");
            }
         }
      } catch(ConcurrentModificationException cme) {
         cme.printStackTrace();
      }
      System.out.println("ConcurrentHashMap after modification: " + map);
      map = new HashMap&lt;String, String&gt;();
      map.put("1", "One");
      map.put("2", "Two");
      map.put("3", "Three");
      map.put("5", "Five");
      map.put("6", "Six");
      System.out.println("Initial HashMap: " + map);
      iterator = map.keySet().iterator();
      try {
         
         while(iterator.hasNext()) {
            String key = iterator.next();
            
            if(key.equals("3")) {
               map.put("4", "Four");
            }
         }
         System.out.println("HashMap after modification: " + map);
      } catch(ConcurrentModificationException cme) {
         cme.printStackTrace();
      }
    } }

    This will produce the following result.

    Output

    Initial ConcurrentHashMap: {1 = One, 2 = Two, 3 = Three, 5 = Five, 6 = Six}
    ConcurrentHashMap after modification: {1 = One, 2 = Two, 3 = Three, 4 = Four, 5 = Five, 6 = Six}
    Initial HashMap: {1 = One, 2 = Two, 3 = Three, 5 = Five, 6 = Six}
    java.util.ConcurrentModificationException
    	at java.util.HashMap$HashIterator.nextNode(Unknown Source)
    	at java.util.HashMap$KeyIterator.next(Unknown Source)
    	at TestThread.main(TestThread.java:48)
    
  • BlockingQueue Interface

    A java.util.concurrent.BlockingQueue interface is a subinterface of Queue interface, and additionally supports operations such as waiting for the queue to become non-empty before retrieving an element, and wait for space to become available in the queue before storing an element.

    BlockingQueue Methods

    Sr.No.Method & Description
    1boolean add(E e)Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions, returning true upon success and throwing an IllegalStateException if no space is currently available.
    2boolean contains(Object o)Returns true if this queue contains the specified element.
    3int drainTo(Collection<? super E> c)Removes all available elements from this queue and adds them to the given collection.
    4int drainTo(Collection<? super E> c, int maxElements)Removes at most the given number of available elements from this queue and adds them to the given collection.
    5boolean offer(E e)Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions, returning true upon success and false if no space is currently available.
    6boolean offer(E e, long timeout, TimeUnit unit)Inserts the specified element into this queue, waiting up to the specified wait time if necessary for space to become available.
    7E poll(long timeout, TimeUnit unit)Retrieves and removes the head of this queue, waiting up to the specified wait time if necessary for an element to become available.
    8void put(E e)Inserts the specified element into this queue, waiting if necessary for space to become available.
    9int remainingCapacity()Returns the number of additional elements that this queue can ideally (in the absence of memory or resource constraints) accept without blocking, or Integer.MAX_VALUE if there is no intrinsic limit.
    10boolean remove(Object o)Removes a single instance of the specified element from this queue, if it is present.
    11E take()Retrieves and removes the head of this queue, waiting if necessary until an element becomes available.

    Example

    The following TestThread program shows usage of BlockingQueue interface in thread based environment.

    import java.util.Random;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.BlockingQueue;
    
    public class TestThread {
    
       public static void main(final String[] arguments) throws InterruptedException {
    
      BlockingQueue&lt;Integer&gt; queue = new ArrayBlockingQueue&lt;Integer&gt;(10);
      Producer producer = new Producer(queue);
      Consumer consumer = new Consumer(queue);
      new Thread(producer).start();
      new Thread(consumer).start();
      Thread.sleep(4000);
    } static class Producer implements Runnable {
      private BlockingQueue&lt;Integer&gt; queue;
      public Producer(BlockingQueue queue) {
         this.queue = queue;
      }
      @Override
      public void run() {
         Random random = new Random();
         try {
            int result = random.nextInt(100);
            Thread.sleep(1000);
            queue.put(result);
            System.out.println("Added: " + result);
            
            result = random.nextInt(100);
            Thread.sleep(1000);
            queue.put(result);
            System.out.println("Added: " + result);
            
            result = random.nextInt(100);
            Thread.sleep(1000);
            queue.put(result);
            System.out.println("Added: " + result);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }	   
    } static class Consumer implements Runnable {
      private BlockingQueue&lt;Integer&gt; queue;
      public Consumer(BlockingQueue queue) {
         this.queue = queue;
      }
      
      @Override
      public void run() {
         
         try {
            System.out.println("Removed: " + queue.take());
            System.out.println("Removed: " + queue.take());
            System.out.println("Removed: " + queue.take());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
    } }

    This will produce the following result.

    Output

    Added: 52
    Removed: 52
    Added: 70
    Removed: 70
    Added: 27
    Removed: 27
    
  • Fork-Join framework

    The fork-join framework allows to break a certain task on several workers and then wait for the result to combine them. It leverages multi-processor machine’s capacity to great extent. Following are the core concepts and objects used in fork-join framework.

    Fork

    Fork is a process in which a task splits itself into smaller and independent sub-tasks which can be executed concurrently.

    Syntax

    Sum left  = new Sum(array, low, mid);
    left.fork();
    

    Here Sum is a subclass of RecursiveTask and left.fork() spilts the task into sub-tasks.

    Join

    Join is a process in which a task join all the results of sub-tasks once the subtasks have finished executing, otherwise it keeps waiting.

    Syntax

    left.join();
    

    Here left is an object of Sum class.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    ForkJoinPool

    it is a special thread pool designed to work with fork-and-join task splitting.

    Syntax

    ForkJoinPool forkJoinPool = new ForkJoinPool(4);
    

    Here a new ForkJoinPool with a parallelism level of 4 CPUs.

    RecursiveAction

    RecursiveAction represents a task which does not return any value.

    Syntax

    class Writer extends RecursiveAction {
       @Override
       protected void compute() { }
    }
    

    RecursiveTask

    RecursiveTask represents a task which returns a value.

    Syntax

    class Sum extends RecursiveTask<Long> {
       @Override
       protected Long compute() { return null; }
    }
    

    Example

    The following TestThread program shows usage of Fork-Join framework in thread based environment.

    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ForkJoinPool;
    import java.util.concurrent.RecursiveTask;
    
    public class TestThread {
    
       public static void main(final String[] arguments) throws InterruptedException, 
    
      ExecutionException {
      
      int nThreads = Runtime.getRuntime().availableProcessors();
      System.out.println(nThreads);
      
      int&#91;] numbers = new int&#91;1000]; 
      for(int i = 0; i &lt; numbers.length; i++) {
         numbers&#91;i] = i;
      }
      ForkJoinPool forkJoinPool = new ForkJoinPool(nThreads);
      Long result = forkJoinPool.invoke(new Sum(numbers,0,numbers.length));
      System.out.println(result);
    } static class Sum extends RecursiveTask<Long> {
      int low;
      int high;
      int&#91;] array;
      Sum(int&#91;] array, int low, int high) {
         this.array = array;
         this.low   = low;
         this.high  = high;
      }
      protected Long compute() {
         
         if(high - low &lt;= 10) {
            long sum = 0;
            
            for(int i = low; i &lt; high; ++i) 
               sum += array&#91;i];
               return sum;
         } else {	    	
            int mid = low + (high - low) / 2;
            Sum left  = new Sum(array, low, mid);
            Sum right = new Sum(array, mid, high);
            left.fork();
            long rightResult = right.compute();
            long leftResult  = left.join();
            return leftResult + rightResult;
         }
      }
    } }

    This will produce the following result.

    Output

    32
    499500
    
  • Futures and Callables

    java.util.concurrent.Callable object can return the computed result done by a thread in contrast to runnable interface which can only run the thread. The Callable object returns Future object which provides methods to monitor the progress of a task being executed by a thread. Future object can be used to check the status of a Callable and then retrieve the result from the Callable once the thread is done. It also provides timeout functionality.

    Syntax

    //submit the callable using ThreadExecutor
    //and get the result as a Future object
    Future<Long> result10 = executor.submit(new FactorialService(10));
     
    //get the result using get method of the Future object
    //get method waits till the thread execution and then return the result of the execution.
    Long factorial10 = result10.get();
    

    Example

    The following TestThread program shows usage of Futures and Callables in thread based environment.

    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class TestThread {
    
       public static void main(final String[] arguments) throws InterruptedException,
    
      ExecutionException {
      ExecutorService executor = Executors.newSingleThreadExecutor();
      System.out.println("Factorial Service called for 10!");
      Future&lt;Long&gt; result10 = executor.submit(new FactorialService(10));
      System.out.println("Factorial Service called for 20!");
      Future&lt;Long&gt; result20 = executor.submit(new FactorialService(20));
      Long factorial10 = result10.get();
      System.out.println("10! = " + factorial10);
      Long factorial20 = result20.get();
      System.out.println("20! = " + factorial20);
      executor.shutdown();
    } static class FactorialService implements Callable<Long> {
      private int number;
      public FactorialService(int number) {
         this.number = number;
      }
      @Override
      public Long call() throws Exception {
         return factorial();
      }
      private Long factorial() throws InterruptedException {
         long result = 1; 
         
         while (number != 0) { 
            result = number * result; 
            number--; 
            Thread.sleep(100); 
         }
         return result;	
      }
    } }

    This will produce the following result.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Output

    Factorial Service called for 10!
    Factorial Service called for 20!
    10! = 3628800
    20! = 2432902008176640000
    
  • ScheduledThreadPoolExecutor Class

    java.util.concurrent.ScheduledThreadPoolExecutor is a subclass of ThreadPoolExecutor and can additionally schedule commands to run after a given delay, or to execute periodically.

    ScheduledThreadPoolExecutor Methods

    Sr.No.Method & Description
    1protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> callable, RunnableScheduledFuture<V> task)Modifies or replaces the task used to execute a callable.
    2protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task)Modifies or replaces the task used to execute a runnable.
    3void execute(Runnable command)Executes command with zero required delay.
    4boolean getContinueExistingPeriodicTasksAfterShutdownPolicy()Gets the policy on whether to continue executing existing periodic tasks even when this executor has been shutdown.
    5boolean getExecuteExistingDelayedTasksAfterShutdownPolicy()Gets the policy on whether to execute existing delayed tasks even when this executor has been shutdown.
    6BlockingQueue<Runnable> getQueue()Returns the task queue used by this executor.
    7boolean getRemoveOnCancelPolicy()Gets the policy on whether cancelled tasks should be immediately removed from the work queue at time of cancellation.
    8<V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)Creates and executes a ScheduledFuture that becomes enabled after the given delay.
    9ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)Creates and executes a one-shot action that becomes enabled after the given delay.
    10ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.
    11ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given delay between the termination of one execution and the commencement of the next.
    12void setContinueExistingPeriodicTasksAfterShutdownPolicy (boolean value)Sets the policy on whether to continue executing existing periodic tasks even when this executor has been shutdown.
    13void setExecuteExistingDelayedTasksAfterShutdownPolicy (boolean value)Sets the policy on whether to execute existing delayed tasks even when this executor has been shutdown.
    14void setRemoveOnCancelPolicy(boolean value)Sets the policy on whether cancelled tasks should be immediately removed from the work queue at time of cancellation.
    15void shutdown()Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
    16List<Runnable> shutdownNow()Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
    17<T> Future<T> submit(Callable<T> task)Submits a value-returning task for execution and returns a Future representing the pending results of the task.
    18Future<?> submit(Runnable task)Submits a Runnable task for execution and returns a Future representing that task.
    19<T> Future<T> submit(Runnable task, T result)Submits a Runnable task for execution and returns a Future representing that task.

    Example

    The following TestThread program shows usage of ScheduledThreadPoolExecutor interface in thread based environment.

    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledThreadPoolExecutor;
    import java.util.concurrent.ScheduledFuture;
    import java.util.concurrent.TimeUnit;
    
    public class TestThread {
    
       public static void main(final String[] arguments) throws InterruptedException {
    
      final ScheduledThreadPoolExecutor scheduler = 
         (ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(1);
      final ScheduledFuture&lt;?&gt; beepHandler = 
         scheduler.scheduleAtFixedRate(new BeepTask(), 2, 2, TimeUnit.SECONDS);
      scheduler.schedule(new Runnable() {
         @Override
         public void run() {
            beepHandler.cancel(true);
            scheduler.shutdown();			
         }
      }, 10, TimeUnit.SECONDS);
    } static class BeepTask implements Runnable {
      
      public void run() {
         System.out.println("beep");      
      }
    } }

    This will produce the following result.

    Output

    beep
    beep
    beep
    beep
    
  • ThreadPoolExecutor Class

    java.util.concurrent.ThreadPoolExecutor is an ExecutorService to execute each submitted task using one of possibly several pooled threads, normally configured using Executors factory methods. It also provides various utility methods to check current threads statistics and control them.

    ThreadPoolExecutor Methods

    Sr.No.Method & Description
    1protected void afterExecute(Runnable r, Throwable t)Method invoked upon completion of execution of the given Runnable.
    2void allowCoreThreadTimeOut(boolean value)Sets the policy governing whether core threads may time out and terminate if no tasks arrive within the keep-alive time, being replaced if needed when new tasks arrive.
    3boolean allowsCoreThreadTimeOut()Returns true if this pool allows core threads to time out and terminate if no tasks arrive within the keepAlive time, being replaced if needed when new tasks arrive.
    4boolean awaitTermination(long timeout, TimeUnit unit)Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
    5protected void beforeExecute(Thread t, Runnable r)Method invoked prior to executing the given Runnable in the given thread.
    6void execute(Runnable command)Executes the given task sometime in the future.
    7protected void finalize()Invokes shutdown when this executor is no longer referenced and it has no threads.
    8int getActiveCount()Returns the approximate number of threads that are actively executing tasks.
    9long getCompletedTaskCount()Returns the approximate total number of tasks that have completed execution.
    10int getCorePoolSize()Returns the core number of threads.
    11long getKeepAliveTime(TimeUnit unit)Returns the thread keep-alive time, which is the amount of time that threads in excess of the core pool size may remain idle before being terminated.
    12int getLargestPoolSize()Returns the largest number of threads that have ever simultaneously been in the pool.
    13int getMaximumPoolSize()Returns the maximum allowed number of threads.
    14int getPoolSize()Returns the current number of threads in the pool.
    15BlockingQueue getQueue()Returns the task queue used by this executor.
    15RejectedExecutionHandler getRejectedExecutionHandler()Returns the current handler for unexecutable tasks.
    16long getTaskCount()Returns the approximate total number of tasks that have ever been scheduled for execution.
    17ThreadFactory getThreadFactory()Returns the thread factory used to create new threads.
    18boolean isShutdown()Returns true if this executor has been shut down.
    19boolean isTerminated()Returns true if all tasks have completed following shut down.
    20boolean isTerminating()Returns true if this executor is in the process of terminating after shutdown() or shutdownNow() but has not completely terminated.
    21int prestartAllCoreThreads()Starts all core threads, causing them to idly wait for work.
    22boolean prestartCoreThread()Starts a core thread, causing it to idly wait for work.
    23void purge()Tries to remove from the work queue all Future tasks that have been cancelled.
    24boolean remove(Runnable task)Removes this task from the executor’s internal queue if it is present, thus causing it not to be run if it has not already started.
    25void setCorePoolSize(int corePoolSize)Sets the core number of threads.
    26void setKeepAliveTime(long time, TimeUnit unit)Sets the time limit for which threads may remain idle before being terminated.
    27void setMaximumPoolSize(int maximumPoolSize)Sets the maximum allowed number of threads.
    28void setRejectedExecutionHandler(RejectedExecutionHandler handler)Sets a new handler for unexecutable tasks.
    29void setThreadFactory(ThreadFactory threadFactory)Sets the thread factory used to create new threads.
    30void shutdown()Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
    31List<Runnable> shutdownNow()Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
    32protected void terminated()Method invoked when the Executor has terminated.
    33String toString()Returns a string identifying this pool, as well as its state, including indications of run state and estimated worker and task counts.

    Example

    The following TestThread program shows usage of ThreadPoolExecutor interface in thread based environment.

    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class TestThread {
    	
       public static void main(final String[] arguments) throws InterruptedException {
    
      ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newCachedThreadPool();
      //Stats before tasks execution
      System.out.println("Largest executions: "
         + executor.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + executor.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + executor.getPoolSize());
      System.out.println("Currently executing threads: "
         + executor.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + executor.getTaskCount());
      executor.submit(new Task());
      executor.submit(new Task());
      //Stats after tasks execution
      System.out.println("Core threads: " + executor.getCorePoolSize());
      System.out.println("Largest executions: "
         + executor.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + executor.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + executor.getPoolSize());
      System.out.println("Currently executing threads: "
         + executor.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + executor.getTaskCount());
      executor.shutdown();
    } static class Task implements Runnable {
      public void run() {
         try {
            Long duration = (long) (Math.random() * 5);
            System.out.println("Running Task! Thread Name: " +
               Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(duration);
            System.out.println("Task Completed! Thread Name: " +
               Thread.currentThread().getName());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
    } }

    This will produce the following result.

    Output

    Largest executions: 0
    Maximum allowed threads: 2147483647
    Current threads in pool: 0
    Currently executing threads: 0
    Total number of threads(ever scheduled): 0
    Core threads: 0
    Largest executions: 2
    Maximum allowed threads: 2147483647
    Current threads in pool: 2
    Currently executing threads: 2
    Total number of threads(ever scheduled): 2
    Running Task! Thread Name: pool-1-thread-2
    Running Task! Thread Name: pool-1-thread-1
    Task Completed! Thread Name: pool-1-thread-1
    Task Completed! Thread Name: pool-1-thread-2
    
  • newSingleThreadExecutor Method

    A single thread pool can be obtainted by calling the static newSingleThreadExecutor() method of Executors class.

    Syntax

    ExecutorService executor = Executors.newSingleThreadExecutor();
    

    Where newSingleThreadExecutor method creates an executor that executes a single task at a time.

    Example

    The following TestThread program shows usage of newSingleThreadExecutor method in thread based environment.

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    public class TestThread {
    
       public static void main(final String[] arguments) throws InterruptedException {
    
      ExecutorService executor = Executors.newSingleThreadExecutor();
      try {
         executor.submit(new Task());
         System.out.println("Shutdown executor");
         executor.shutdown();
         executor.awaitTermination(5, TimeUnit.SECONDS);
      } catch (InterruptedException e) {
         System.err.println("tasks interrupted");
      } finally {
         if (!executor.isTerminated()) {
            System.err.println("cancel non-finished tasks");
         }
         executor.shutdownNow();
         System.out.println("shutdown finished");
      }
    } static class Task implements Runnable {
      
      public void run() {
         try {
            Long duration = (long) (Math.random() * 20);
            System.out.println("Running Task!");
            TimeUnit.SECONDS.sleep(duration);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
    } }

    This will produce the following result.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Output

    Shutdown executor
    Running Task!
    shutdown finished
    cancel non-finished tasks
    java.lang.InterruptedException: sleep interrupted
    	at java.lang.Thread.sleep(Native Method)
    	at java.lang.Thread.sleep(Thread.java:302)
    	at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:328)
    	at TestThread$Task.run(TestThread.java:39)
    	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
    	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    	at java.lang.Thread.run(Thread.java:662)
    
  • newScheduledThreadPool Method

    A scheduled thread pool can be obtainted by calling the static newScheduledThreadPool() method of Executors class.

    Syntax

    ExecutorService executor = Executors.newScheduledThreadPool(1);
    

    Example

    The following TestThread program shows usage of newScheduledThreadPool method in thread based environment.

    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.ScheduledFuture;
    import java.util.concurrent.TimeUnit;
    
    public class TestThread {
    
       public static void main(final String[] arguments) throws InterruptedException {
    
      final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
      final ScheduledFuture&lt;?&gt; beepHandler = 
         scheduler.scheduleAtFixedRate(new BeepTask(), 2, 2, TimeUnit.SECONDS);
      scheduler.schedule(new Runnable() {
         @Override
         public void run() {
            beepHandler.cancel(true);
            scheduler.shutdown();			
         }
      }, 10, TimeUnit.SECONDS);
    } static class BeepTask implements Runnable {
      public void run() {
         System.out.println("beep");      
      }
    } }

    This will produce the following result.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Output

    beep
    beep
    beep
    beep
    
  • newCachedThreadPool Method

    A cached thread pool can be obtainted by calling the static newCachedThreadPool() method of Executors class.

    Syntax

    ExecutorService executor = Executors.newCachedThreadPool();
    

    where

    • newCachedThreadPool method creates an executor having an expandable thread pool.
    • Such an executor is suitable for applications that launch many short-lived tasks.

    Example

    The following TestThread program shows usage of newCachedThreadPool method in thread based environment.

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class TestThread {
    	
       public static void main(final String[] arguments) throws InterruptedException {
    
      ExecutorService executor = Executors.newCachedThreadPool();
      // Cast the object to its class type
      ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;
      //Stats before tasks execution
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());
      executor.submit(new Task());
      executor.submit(new Task());
      //Stats after tasks execution
      System.out.println("Core threads: " + pool.getCorePoolSize());
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());
      executor.shutdown();
    } static class Task implements Runnable {
      public void run() {
         
         try {
            Long duration = (long) (Math.random() * 5);
            System.out.println("Running Task! Thread Name: " +
               Thread.currentThread().getName());
               TimeUnit.SECONDS.sleep(duration);
            System.out.println("Task Completed! Thread Name: " +
               Thread.currentThread().getName());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
    } }

    This will produce the following result.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Output

    Largest executions: 0
    Maximum allowed threads: 2147483647
    Current threads in pool: 0
    Currently executing threads: 0
    Total number of threads(ever scheduled): 0
    Core threads: 0
    Largest executions: 2
    Maximum allowed threads: 2147483647
    Current threads in pool: 2
    Currently executing threads: 2
    Total number of threads(ever scheduled): 2
    Running Task! Thread Name: pool-1-thread-1
    Running Task! Thread Name: pool-1-thread-2
    Task Completed! Thread Name: pool-1-thread-2
    Task Completed! Thread Name: pool-1-thread-1