Google

Jul 5, 2014

Java Executor service to run concurrently and sequentially with strategy design pattern - part 3

1. Define the interface

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.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;

public interface ExecutorStrategy {
 ExecutorService getExecutor(Collection<? extends Callable> tasks);
 ExecutorService getExecutor(Callable<?>... tasks);
}


2. Define the implementation.

package com.writtentest13;

import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 * What is the strategy to execute sequentially in current thread or concurrently?
 * 
 * if no of tasks > threshold then concurrent, else sequentially single
 */
public class TaskExecutorStrategy implements ExecutorStrategy {

 public static final int DEFAULT_THRESHOLD = 1;

 private int threshold = DEFAULT_THRESHOLD;

 private ExecutorService currentThreadExecutor;
 private ExecutorService concurrentExecutor;

 public TaskExecutorStrategy() {
    init();
 }

 public TaskExecutorStrategy(int threshold, int poolSize) {
    this.threshold = threshold;
    init();
 }

 
 private void init() {
    this.currentThreadExecutor = new DefaultThreadExecutor();
    this.concurrentExecutor = Executors.newCachedThreadPool();
 }

 @Override
 public ExecutorService getExecutor(Collection<? extends Callable> tasks) {
    return (tasks.size() > this.threshold) ? this.concurrentExecutor : this.currentThreadExecutor;

 }

 @Override
 public ExecutorService getExecutor(Callable<?>... tasks) {
    return (tasks.length > this.threshold) ? this.concurrentExecutor : this.currentThreadExecutor;
 }

}


3. Use the strategy

package com.writtentest13;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;

/**
 * Tasks are executed concurrently in a thread pool
 */
public class ThreadExecutorMainStrategy  {

 private ExecutorStrategy executorStrategy;

 public static void main(String[] args) {
    ThreadExecutorMainStrategy main = new ThreadExecutorMainStrategy();

  
  List<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();

  // create dummy tasks
  for (int i = 1; i <= 5; i++) {
     tasks.add(main.createTask(i));
  }
  
  
  main.executorStrategy = new TaskExecutorStrategy();
  ExecutorService executor = main.executorStrategy.getExecutor(tasks);
  
 
  // submit the tasks to the concurrentThreadExecutor
  try {
    executor.invokeAll(tasks);

  } 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

Performing task 1 on thread - pool-1-thread-1
Performing task 3 on thread - pool-1-thread-3
Performing task 2 on thread - pool-1-thread-2
Performing task 5 on thread - pool-1-thread-5
Performing task 4 on thread - pool-1-thread-4
Completed .........


Now if you change the execution strategy arguments to

//threshold = 7, no of threads  = 5
main.executorStrategy = new TaskExecutorStrategy(7,5);


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 .........


You can create different strategies by implementing the interface ExecutorStrategy.

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home