Package com.level3.meanwhile

Source Code of com.level3.meanwhile.TaskQueue

package com.level3.meanwhile;

import com.level3.meanwhile.state.ClaimCheck;
import com.level3.meanwhile.concurrent.MeanwhileFuture;
import com.level3.meanwhile.concurrent.MeanwhileRunner;
import com.level3.meanwhile.concurrent.MeanwhileThreadPoolExecutor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;


/**
* Class that creates and manages a java thread pool for use in executing generic asynchronous tasks.
* There may be many of these pools available per JVM.
*
* <p>Currently backed by a boundless LinkedBlockingQueue. This means that the queue will continue to
* grow infinitely. May want to consider bounding this in the future and throwing exceptions
* if queue length exceeded.
*
* @author Jonathan Griggs <Jonathan.Griggs@Level3.com>
* @since 0.1
*/

public final class TaskQueue {
  private int defaultNumThreads;
        private int defaultStageThreads;
        private LinkedBlockingQueue<Runnable> queue;
  private MeanwhileThreadPoolExecutor pool;
        private LinkedBlockingQueue<Runnable> stageQueue;
  private MeanwhileThreadPoolExecutor stagePool;
 
  //Static class, prevent instantiation
  public TaskQueue(final int numThreads, final int numStageThreads){
            this.defaultNumThreads = numThreads;
            this.defaultStageThreads = numStageThreads;
        };
 
  /**
   * Starts up the ThreadPool with the default number of threads - specified in properties
   * @since 0.1
         */
  private void startUp() {
            startUp(defaultNumThreads,defaultStageThreads);
  }
 
  /**
   * Starts up the ThreadPool with the specified number of threads
   * @since 0.1
         */
  private void startUp(final int maxNumThreads, final int maxNumStageThreads) {
    if(!isPoolStarted()) {
      queue = new LinkedBlockingQueue<Runnable>();
      pool = new MeanwhileThreadPoolExecutor(maxNumThreads, maxNumThreads, 0, TimeUnit.SECONDS, queue);
    }
                if(!isStagePoolStarted()) {
                        stageQueue = new LinkedBlockingQueue<Runnable>();
      stagePool = new MeanwhileThreadPoolExecutor(maxNumStageThreads, maxNumStageThreads, 0, TimeUnit.SECONDS, stageQueue);
    }
  }
       
        /**
   * Sets the maximum number of threads available for concurrent Task execution.
         * If the number is lower than the current number of busy threads, the pool will wait until those threads finish
         * and scale back the number of threads as they are returned to the pool
         * @param max The maximum number of Tasks that should be executed concurrently. Must be > 0.
   * @since 0.1
         */
  public void setMaximumThreadCount(final int max) {
            defaultNumThreads = max;
            startUp();
            pool.setCorePoolSize(max);
            pool.setMaximumPoolSize(max);
  }
       
        /**
   * Sets the maximum number of threads available for concurrent Task execution.
         * If the number is lower than the current number of busy threads, the pool will wait until those threads finish
         * and scale back the number of threads as they are returned to the pool
         * @param max The maximum number of Tasks that should be executed concurrently. Must be > 0.
   * @since 0.1
         */
  public void setMaximumStagePoolThreadCount(final int max) {
                defaultStageThreads = max;
                startUp();
                stagePool.setCorePoolSize(max);
                stagePool.setMaximumPoolSize(max);
  }
       
        /**
   * Adds a task into the executor thread pool, and returns a Claim Check
         * @param task The Task to be executed
         * @return a ClaimCheck that may be redeemed to cancel this task
   * @since 0.1
         * @see Task
         * @see ClaimCheck
         * @see Future
         */
  public <T extends Task> ClaimCheck execute(final T task) {
    startUp();
                MeanwhileFuture<T> future = new MeanwhileFuture<T>(new MeanwhileRunner(task,this));
                if(task instanceof Stage) {
                    stagePool.execute(future);
                } else {
                    pool.execute(future);
                }
                return future.getClaimCheck();
  }
       
        /**
   * Adds multiple tasks into the executor thread pool, and returns a list of Claim Checks
         *
         * @param tasks A list of Tasks to be executed
         * @return a List of Futures that wrap the Tasks submitted to the work queue
   * @since 0.1
         * @see Task
         * @see Future
         */
  public <T extends Task> List<ClaimCheck> execute(final List<T> tasks) {
            startUp();
            List<ClaimCheck> claimChecks = new ArrayList<ClaimCheck>();
            for(T task : tasks) {
                claimChecks.add(this.execute(task));
            }
            return claimChecks;
  }
 
  /**
   * Adds a task into the executor thread pool, and returns a Future
         * @param task The Task to be executed
         * @return the completed Task that was executed
   * @since 0.1
         * @see Task
         * @see Future
         */
  public <T extends Task> MeanwhileFuture<T> submit(final T task) {
    startUp();
                MeanwhileFuture<T> future = new MeanwhileFuture<T>(new MeanwhileRunner(task,this));
                if(task instanceof Stage) {
                    stagePool.execute(future);
                } else {
                    pool.execute(future);
                }
                return future;
  }
       
        /**
   * Adds a task into the executor thread pool, and returns a Future
         * @param mr An instance of MeanwhileRunner (which wraps a Task) to be executed
         * @return the completed Task that was executed
   * @since 0.1
         * @see Task
         * @see Future
         */
  public <T extends Task> MeanwhileFuture<T> submit(final MeanwhileRunner<T> mr) {
    startUp();
                MeanwhileFuture<T> future = new MeanwhileFuture<T>(mr);
                if(mr.getTask() instanceof Stage) {
                    stagePool.execute(future);
                } else {
                    pool.execute(future);
                }
                return future;
  }
       
        /**
   * Adds multiple tasks into the executor thread pool, and returns a list of Futures
         *
         * @param tasks A list of Tasks to be executed
         * @return a List of Futures that wrap the Tasks submitted to the work queue
   * @since 0.1
         * @see Task
         * @see Future
         */
  public <T extends Task> List<MeanwhileFuture<T>> submit(final List<T> tasks) {
            startUp();
            List<MeanwhileFuture<T>> futures = new ArrayList<MeanwhileFuture<T>>();
            for(T task : tasks) {
                futures.add(this.submit(task));
            }
            return futures;
  }
 
  /**
   * Takes a list of Tasks, submits each one to the Executor pool, and effectively WAITS until
   * all those tasks are completed and then returns a list of the completed tasks in the order they were submitted (i.e., not in the order
   * they finished)
   * 
   * <p>This allows the client to parallelize work in the context of a single synchronous
   * call.
         * @param tasks A list of Tasks to be executed
         * @return a List of completed Tasks that were executed
   * @since 0.1
         * @see Task
         */
  public <T extends Task> List<T> blockingSubmit(final List<T> tasks) throws Exception {
                startUp();
                List<T> list = new ArrayList<T>();
    for(Future<T> future : this.submit(tasks)) {
                    list.add(future.get());
                }
    return list; 
  }
       
        /**
   * Takes a single Task, submits it to the Executor pool, and effectively WAITS until
   * the task is completed and then returns the Task
   * 
   * <p>This allows the client to parallelize work in the context of a single synchronous
   * call.
         * @param task The Task to be executed
         * @return the completed Task that was executed
   * @since 0.1
         * @see Task
         */
  public <T extends Task> T blockingSubmit(final T task) throws Exception {
                startUp();
    return this.blockingSubmit(Arrays.asList(task)).get(0);
  }
       
        /**
         *
         * private helper method for blocking on ClaimCheck/UUID/UUID String
         *
        
         * @return <b>{@code true}</b> if the TaskManager has found the Task represented by the object and successfully waited for
         * execution. A <b>{@code false}</b> is returned if the TaskManager did not find a Task represented by the object and therefore
         * did not actually block (i.e., it returned immediately)
         * @param obj an object representing ClaimCheck / UUID / UUID String of the Task we wish to block on
         * @since 0.2.1
         * @see ClaimCheck
   */
  private boolean blockHelper(final Object obj) throws Exception {
            startUp();
            boolean blocked = false;
            MeanwhileFuture future = stagePool.getFuture(obj);
            if(future!=null) {
                blocked = true;
                future.get();
            } else {
                future = pool.getFuture(obj);
                if(future!=null) {
                    blocked = true;
                    future.get();
                }
            }
            return blocked;
  }
       
        /**
         *
         * Blocks until the task(s) represented by the ClaimCheck have finished processing.
         *
         * <p>This method is very useful for use cases where the client has a ClaimCheck and needs to halt further processing, but
         * is for some reason unable to make an initial blockingSubmit() call. Unit Tests are a good example of this use case.
         *
         * @return <b>{@code true}</b> if the TaskManager has found the Task represented by the ClaimCheck and successfully waited for
         * execution. A <b>{@code false}</b> is returned if the TaskManager did not find a Task represented by the ClaimCheck and therefore
         * did not actually block (i.e., it returned immediately)
         * @param claim the ClaimCheck of the Task we wish to block on
         * @since 0.2.1
         * @see ClaimCheck
   */
  public boolean block(final ClaimCheck claim) throws Exception {
            return blockHelper(claim);
  }
       
        /**
         *
         * Blocks until the task(s) represented by the UUID have finished processing.
         *
         * <p>This method is very useful for use cases where the client has a UUID and needs to halt further processing, but
         * is for some reason unable to make an initial blockingSubmit() call. Unit Tests are a good example of this use case.
         *
         * @return <b>{@code true}</b> if the TaskManager has found the Task represented by the UUID and successfully waited for
         * execution. A <b>{@code false}</b> is returned if the TaskManager did not find a Task represented by the UUID and therefore
         * did not actually block (i.e., it returned immediately)
         * @param uuid the UUID of the Task we wish to block on
         * @since 0.2.1
         * @see ClaimCheck
         * @see UUID
   */
  public boolean block(final UUID uuid) throws Exception {
            return blockHelper(uuid);
  }
       
        /**
         *
         * Blocks until the task(s) represented by the UUID String have finished processing.
         *
         * <p>This method is very useful for use cases where the client has a UUID String and needs to halt further processing, but
         * is for some reason unable to make an initial blockingSubmit() call. Unit Tests are a good example of this use case.
         *
         * @return <b>{@code true}</b> if the TaskManager has found the Task represented by the UUID String and successfully waited for
         * execution. A <b>{@code false}</b> is returned if the TaskManager did not find a Task represented by the UUID String and therefore
         * did not actually block (i.e., it returned immediately)
         * @param sUuid the UUID String of the Task we wish to block on
         * @since 0.2.1
         * @see ClaimCheck
         * @see UUID
   */
  public boolean block(final String sUuid) throws Exception {
            return blockHelper(sUuid);
  }
 
  /**
         * private helper method
         *
   * <p>Cancels a task that has been scheduled for execution. If task is already in process,
   * this will do nothing.
         * @return <b>{@code true}</b> if the Task has been canceled, <b>{@code false}</b> if the Task could not be canceled,
         * because it is already in TaskStatus.WORKING, or because it simply does not exist in the queue.
   * @since 0.1
         */
  private boolean cancelHelper(final Object task) {
            startUp();
            boolean canceled = false;
            if(pool.cancel(task)) {
                canceled = true;
            }
            if(stagePool.cancel(task)) {
                canceled = true;
            }
            return canceled;
  }
       
        /**
         *
         * Cancels a task that has been scheduled for execution. If task is already in process,
   * this will do nothing.
         *
         * <p>Cancel will prevent the execution of all incomplete, not-in-flight Tasks that match the Claim Check,
         * as well as all subtasks that have yet to complete or begin processing.
         *
         * <p>For instance, consider a scenario with a Chain of Tasks:
         *
         * <p>     Task 1 (Complete) -> Task 2 (Working) -> Task 3 (Queued) -> Task 4 (Queued)
         *
         * <p>Passing in the ClaimCheck for Task 1 (returned from TaskManager.execute()) will result in the cancellation of Task 3 and Task 4.
         *
         * @return <b>{@code true}</b> if the Task has been canceled, <b>{@code false}</b> if the Task could not be canceled,
         * because it is already in TaskStatus.WORKING, or because it simply does not exist in the queue.
         * @param claim the ClaimCheck of the task to be canceled
         * @since 0.1
         * @see Task
   */
  public boolean cancel(final ClaimCheck claim) {
            return cancelHelper(claim);
  }
       
        /**
         *
         * Cancels a queued task that matches the provided UUID. If task is already in process, this will do nothing.
         *
          * <p>Cancel will prevent the execution of all incomplete, not-in-flight Tasks that match the UUID,
         * as well as all subtasks that have yet to complete or begin processing.
         *
         * @return <b>{@code true}</b> if the Task has been canceled, <b>{@code false}</b> if the Task could not be canceled,
         * because it is already in TaskStatus.WORKING, or because it simply does not exist in the queue.
   * @param uuid the UUID of the Task to be canceled
         * @since 0.1
         * @see UUID
   */
  public boolean cancel(final UUID uuid) {
            return cancelHelper(uuid);
  }
       
        /**
         * Cancels a queued task that matches the provided UUID string. If task is already in process,
   * this will do nothing.
         *
         * <p>Cancel will prevent the execution of all incomplete, not-in-flight Tasks that match the UUID string,
         * as well as all subtasks that have yet to complete or begin processing.
         *
         * @return <b>{@code true}</b> if the Task has been canceled, <b>{@code false}</b> if the Task could not be canceled,
         * because it is already in TaskStatus.WORKING, or because it simply does not exist in the queue.
   * @param uuid a String representing the UUID of the Task
         * @since 0.1
         * @see UUID#toString
   */
  public boolean cancel(final String uuid) {
            return cancelHelper(uuid);
  }
       
  /**
   * Returns the current queue size. This number represents the number of Tasks currently <i>waiting</i> to be
         * executed, and not the number of Tasks currently being executed.
         * @return the current size of the Task work queue
   * @since 0.1
         */
  public int getQueueSize() {
                startUp();
    return pool.getQueue().size();
  }
       
        /**
   * Returns the current queue size. This number represents the number of Tasks currently <i>waiting</i> to be
         * executed, and not the number of Tasks currently being executed.
         * @return the current size of the Task work queue
   * @since 0.1
         */
  public int getStageQueueSize() {
                startUp();
    return stagePool.getQueue().size();
  }
       
        /**
   * Returns the maximum number of threads that are available for concurrent execution of Tasks. This is not reflective of the
         * current number of Tasks currently in WORKING state.
         * @return the maximum number of Tasks that may be executed concurrently
   * @since 0.1
         */
  public int getMaximumPoolSize() {
                startUp();
    return pool.getMaximumPoolSize();
  }
       
        /**
   * Returns the current number of threads that are busy executing Tasks.
         * @return the number of threads that are currently busy executing tasks
   * @since 0.1
         */
  public int getActiveCount() {
                startUp();
    return pool.getActiveCount();
  }
       
        /**
   * Gets a list of all of the queued Tasks
         * @return a List of ClaimChecks for all of the queued Tasks
   * @since 0.2
         * @see ClaimCheck
         */
  public List<ClaimCheck> getQueuedTasks() {
            startUp();
            List<ClaimCheck> list = new ArrayList<ClaimCheck>();
            for(Runnable r : pool.getQueue()) {
                if(r instanceof MeanwhileFuture) {
                    list.add(((MeanwhileFuture)r).getClaimCheck());
                }
            }
            return list;
  }
       
        /**
   * Gets a list of all of the Tasks currently in-flight
         * @return a List of ClaimChecks for all of the active  Tasks
   * @since 0.2
         * @see ClaimCheck
         */
  public List<ClaimCheck> getActiveTasks() {
            startUp();
            List<ClaimCheck> list = new ArrayList<ClaimCheck>();
            for(MeanwhileFuture future : pool.getActiveFutures()) {
                list.add(future.getClaimCheck());
            }
            return list;
  }
 
  /**
   * Reports whether the specified Task is queued for execution.
         * @return <b>{@code true}</b> if the Task has been queued, <b>{@code false}</b> otherwise
   * @since 0.1
         * @see Task
         */
  public boolean isQueued(final Object claimCheck) {
            startUp();
            for(Runnable r : pool.getQueue()) {
                if(r.equals(claimCheck)) {
                    return true;
                }
            }
            for(Runnable r : stagePool.getQueue()) {
                if(r.equals(claimCheck)) {
                    return true;
                }
            }
            return false;
  }
  /**
   * Reports the current position of the specified task within the queue
   * returns -1 if not in the queue
         * @return the index of the Task within the work queue, -1 if not found
   * @since 0.1
         * @see Task
         */
  public int getQueuePosition(final Object claimCheck) {
    int i = 1;
    for(Object r : pool.getQueue().toArray()) {
      if(r.equals(claimCheck))
        return i;
      i++;
    }
                i = 1;
    for(Object r : stagePool.getQueue().toArray()) {
      if(r.equals(claimCheck))
        return i;
      i++;
    }
    return -1;
  }
       
  /**
   * Shuts down the Executor pool immediately
   * @since 0.1
         */
  public void shutdown() {
    if(pool!=null)
                    pool.shutdownNow();
                if(stagePool!=null)
                    stagePool.shutdownNow();
  }
 
  /**
   * Shuts down the Executor pool, specifying the amount of time to wait for tasks to finish
   * @since 0.1
         */
  public void shutdown(final long millisToWait) {
    if(pool!=null) {
     
                    pool.shutdown();
                    try {
                            pool.awaitTermination(millisToWait, TimeUnit.MILLISECONDS);
                    } catch(Exception e) {
                            throw new RuntimeException("Error shutting down TaskManager " + e.toString());
                    }
                    pool.shutdownNow();
                }
               
                if(stagePool!=null) {
     
                    stagePool.shutdown();
                    try {
                            stagePool.awaitTermination(millisToWait, TimeUnit.MILLISECONDS);
                    } catch(Exception e) {
                            throw new RuntimeException("Error shutting down TaskManager " + e.toString());
                    }
                    stagePool.shutdownNow();
                }
  }
       
        /**
   * Returns the status of the pool.
         * @return true if the pool has started, false if it is shutdown
   * @since 0.1
         */
  public boolean isPoolStarted() {
            if(pool==null||pool.isShutdown()) {
                return false;
            }
            return true;
        }
       
        /**
   * Returns the status of the stage pool.
         * @return true if the stage pool has started, false if it is shutdown
   * @since 0.1
         */
  public boolean isStagePoolStarted() {
            if(stagePool==null||stagePool.isShutdown()) {
                return false;
            }
            return true;
        }
}
TOP

Related Classes of com.level3.meanwhile.TaskQueue

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.