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