Java Executor service to run concurrently and sequentially with strategy design pattern - part 2
Firstly, write a default executor by extending AbstractExecutorService class and implementing the relevant methods like shutdown(), execute(Runnable command), etc.
Part 1: Running concurrent threads
Part 2: Running sequential threads
Part 3: Creating a strategy class using the strategy design pattern to be able switch between running concurrently and sequentially.
package com.writtentest13; import java.util.Collections; import java.util.List; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; public class DefaultThreadExecutor extends AbstractExecutorService { private boolean flagShutdown = false; // shut down flag private AtomicLong executingTasks = new AtomicLong(); // atomic counter private Object terminationMutex = new Object(); @Override public void shutdown() { this.flagShutdown = true; } @Override public List<Runnable> shutdownNow() { shutdown(); // best practice to favor empty collection over a null. return Collections.emptyList(); } @Override public boolean isShutdown() { return this.flagShutdown; } @Override public boolean isTerminated() { return (isShutdown() && (this.executingTasks.get() == 0)); } @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { if (isTerminated()) { return true; } // favor TimeUnit class to Thread.sleep synchronized (this.terminationMutex) { this.terminationMutex.wait(unit.toMillis(timeout)); // waiting to be // notified } return isTerminated(); } @Override public void execute(Runnable command) { if (isShutdown()) { throw new IllegalStateException("The executor is already shutdown."); } this.executingTasks.incrementAndGet(); System.out.println("Starting to execute task ..." ); command.run(); // run it on a thread System.out.println("Finished executing task ..." ); long remaining = this.executingTasks.decrementAndGet(); if (isShutdown() && (remaining == 0)) { synchronized (this.terminationMutex) { terminationMutex.notifyAll(); // notify waiting threads } } } }
Use the above method in the main class shown below to run sequentially in the main thread itself.
package com.writtentest13; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; /** * * Tasks are executed sequentially on the current thread * */ public class ThreadExecutorMainSeq { private ExecutorService currentThreadExecutor; public static void main(String[] args) { ThreadExecutorMainSeq main = new ThreadExecutorMainSeq(); //sequential executor main.currentThreadExecutor = new DefaultThreadExecutor(); List<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>(); //create dummy tasks for (int i = 1; i <= 5; i++) { tasks.add(main.createTask(i)); } //submit the tasks to the currentThreadExecutor try { main.currentThreadExecutor.invokeAll(tasks); while(main.currentThreadExecutor.awaitTermination(2, TimeUnit.SECONDS)){ } } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Completed ........."); } private Callable<Boolean> createTask(final int i) { Callable<Boolean> task = new Callable<Boolean>() { @Override public Boolean call() throws Exception { System.out.println("Performing task " + i + " on thread - " + Thread.currentThread().getName()); return true; } }; return task; } }
The output will be
Starting to execute task ... Performing task 1 on thread - main Finished executing task ... Starting to execute task ... Performing task 2 on thread - main Finished executing task ... Starting to execute task ... Performing task 3 on thread - main Finished executing task ... Starting to execute task ... Performing task 4 on thread - main Finished executing task ... Starting to execute task ... Performing task 5 on thread - main Finished executing task ... Completed .........
Labels: Multi-threading
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home