Package org.apache.droids.impl

Source Code of org.apache.droids.impl.MultiThreadedTaskMaster$TaskExecutorPool

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.droids.impl;

import java.util.Date;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.droids.api.DelayTimer;
import org.apache.droids.api.Droid;
import org.apache.droids.api.Task;
import org.apache.droids.api.TaskExceptionHandler;
import org.apache.droids.api.TaskExceptionResult;
import org.apache.droids.api.TaskMaster;
import org.apache.droids.api.WorkMonitor;
import org.apache.droids.api.Worker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Responsible for running all the tasks
*/
public class MultiThreadedTaskMaster<T extends Task> implements TaskMaster<T>
{

  protected static final Logger LOG = LoggerFactory.getLogger(MultiThreadedTaskMaster.class);
  private static final long TICKLE_TIME = 1000L;
 
  /**
   * The execution state
   */
  protected volatile ExecutionState state = ExecutionState.STOPPED;
  /**
   * The delay timer
   */
  protected DelayTimer delayTimer;
  /**
   * The start time
   */
  protected Date startTime;
  /**
   * The end time
   */
  protected Date endTime;
  /**
   * The last completed task
   */
  protected T lastCompletedTask;
  /**
   * The completed task counter
   */
  protected AtomicLong completedTasks = new AtomicLong();
  /**
   * The monitor that that records the processing of tasks
   */
  protected WorkMonitor<T> monitor;
  /**
   * The task exception handler
   */
  protected TaskExceptionHandler exceptionHandler;

  /*
   * The pool size
   */
  private int poolSize = 1;
  /**
   * The pool
   */
  private TaskExecutorPool pool;

  @Override
  public void start(Queue<T> queue, Droid<T> droid)
  {
    if (LOG.isInfoEnabled()) {
      LOG.info("Start the executor service.");
    }

    state = ExecutionState.RUNNING;

    if (pool == null) {
      this.pool = new TaskExecutorPool();
      this.pool.setCorePoolSize(this.poolSize);
    }

    // Stagger startup
    for (int i = 0; i < poolSize; i++) {
      try {
        Thread.sleep(TICKLE_TIME);
      } catch(InterruptedException ignored) {
        LOG.error("", ignored);
      }
      pool.execute(new TaskExecutor(droid));
    }
  }

  /**
   * Stops the TaskMaster
   */
  public void stop()
  {
    // debug
    if (LOG.isInfoEnabled()) {
      LOG.info("Stop the executor service.");
    }

    state = ExecutionState.STOPPED;

    // Disable new tasks from being submitted
    pool.shutdown();

    // Wait a while for existing tasks to terminate
    try {
      if (!pool.awaitTermination(1, TimeUnit.SECONDS)) {

        // Cancel currently executing tasks
        pool.shutdownNow();

        // Wait a while for to respond to being canceled
        if (!pool.awaitTermination(1, TimeUnit.SECONDS)) {
          if (LOG.isInfoEnabled()) {
            LOG.info("Scheduler did not stop.");
          }
        }
      }
    } catch (InterruptedException ex) {

      if (LOG.isInfoEnabled()) {
        LOG.info("Force scheduler to stop.");
      }

      // (Re-)Cancel if current thread also interrupted
      pool.shutdownNow();

      // Preserve interrupt status
      Thread.currentThread().interrupt();
    }

    // debug
    if (LOG.isInfoEnabled()) {
      LOG.info("Scheduler stopped.");
    }

  }

  @Override
  public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
  {
    return pool.awaitTermination(timeout, unit);
  }

  /**
   * @inheritDoc
   */
  @Override
  public ExecutionState getExecutionState()
  {
    return state;
  }

  /**
   * @return
   * @inheritDoc
   */
  public WorkMonitor<T> getMonitor()
  {
    return monitor;
  }

  /**
   * @param monitor
   * @inheritDoc
   */
  public void setMonitor(WorkMonitor<T> monitor)
  {
    if (state == ExecutionState.RUNNING) {
      throw new IllegalStateException("The TaskMaster must be stopped to set a Monitor.");
    }
    this.monitor = monitor;
  }

  @Override
  public void setExceptionHandler(TaskExceptionHandler exceptionHandler)
  {
    this.exceptionHandler = exceptionHandler;
  }

  @Override
  public void setDelayTimer(DelayTimer delayTimer)
  {
    this.delayTimer = delayTimer;
  }

  @Override
  public Date getFinishedWorking()
  {
    return endTime;
  }

  @Override
  public T getLastCompletedTask()
  {
    return lastCompletedTask;
  }

  @Override
  public long getCompletedTasks()
  {
    return completedTasks.get();
  }

  @Override
  public Date getStartTime()
  {
    return startTime;
  }

  /**
   * Sets the pool size
   *
   * @return
   */
  public int getPoolSize()
  {
    return poolSize;
  }

  /**
   * Returns the size of the pool
   *
   * @param poolSize
   */
  public void setPoolSize(int poolSize)
  {
    this.poolSize = poolSize;
    if(pool != null)
      pool.setCorePoolSize(this.poolSize);
  }

  private class TaskExecutorPool extends ThreadPoolExecutor
  {

    private static final long KEEP_ALIVE = 50000L;

    public TaskExecutorPool()
    {
      super(poolSize, poolSize, KEEP_ALIVE, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
      this.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
    }

    @Override
    protected void afterExecute(Runnable r, Throwable thrwbl)
    {
      super.afterExecute(r, thrwbl);

     
     
      // try to reexecute the task runner while
      // the task queue is not empty and while the pool
      // is still completing the execution of tasks.
      @SuppressWarnings("unchecked")
      TaskExecutor taskExecutor = (TaskExecutor) r;
     
      while (taskExecutor.getQueue().size() > 0 || getQueue().size() > 0) {
        if (taskExecutor.getQueue().size() > 0) {
          execute(r);
          return;
        }
        try {
          Thread.sleep(TICKLE_TIME);
        } catch (InterruptedException e) {
          LOG.error("", e);
        }
      }
     
      state = ExecutionState.COMPLETED;
      // If this point is reached, a count of one means this completed thread
      if(this.getActiveCount() == 1) {
       
      // finish droid just once 
        taskExecutor.getDroid().finished();
        shutdown();
      }

    }
  }

  private class TaskExecutor implements Runnable
  {

    private final Droid<T> droid;
    private final Queue<T> queue;
    private final Worker<T> worker;

    public TaskExecutor(Droid<T> droid)
    {
      this.droid = droid;
      this.queue = droid.getQueue();
      this.worker = droid.getNewWorker();
    }

    public Droid<T> getDroid()
    {
      return droid;
    }

    public Queue<T> getQueue()
    {
      return queue;
    }

    @SuppressWarnings("unused")
    public Worker<? extends Task> getWorker()
    {
      return worker;
    }

    @Override
    public void run()
    {
      // poll the last task
      T task = queue.poll();
     
      if(task == null) {
        try {
          Thread.sleep(TICKLE_TIME);
        } catch (InterruptedException e) {
          LOG.error("", e);
        }
        task = queue.poll();
      }

      // execute the task
      if (task != null) {
        try {
          // monitor the execution of the task
          if (monitor != null) {
            monitor.beforeExecute(task, worker);
          }

          // debug
          if (LOG.isDebugEnabled()) {
            LOG.debug("Worker [" + worker + "] execute task [" + task + "].");
          }

          // execute the task
          if(!task.isAborted()) {
            worker.execute(task);
          }

          // debug
          if (LOG.isDebugEnabled()) {
            LOG.debug("Worker [" + worker + "] executed task [" + task + "] with success.");
          }

          // monitor the execution of the task
          if (monitor != null) {
            monitor.afterExecute(task, worker, null);
          }

          // set the monitored variables
          completedTasks.incrementAndGet();
          lastCompletedTask = task;

        } catch (Exception ex) {
          // debug
          if (LOG.isDebugEnabled()) {
            LOG.debug("Worker [" + worker + "] executed task [" + task + "] without success.");
          }

          // debug
          if (LOG.isErrorEnabled()) {
            LOG.error("", ex);
          }

          // monitor the exception
          if (monitor != null) {
            monitor.afterExecute(task, worker, ex);
          }

          // handler the exception
          if (ex != null) {
            TaskExceptionResult result = exceptionHandler.handleException(ex);

            // stop the execution in case of a fatal exception
            if (TaskExceptionResult.FATAL.equals(result)) {
              state = ExecutionState.STOPPED;
              droid.finished();
              pool.shutdownNow();
            }
          }
        }
      }
    }
  }
}
TOP

Related Classes of org.apache.droids.impl.MultiThreadedTaskMaster$TaskExecutorPool

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.