/** * Alipay.com Inc. * Copyright (c) 2004-2012 All Rights Reserved. */ package com.alipay.zdal.datasource.resource.util.threadpool; import org.apache.log4j.Logger; /** * A wrapper for the task. * * @author ���� * @version $Id: BasicTaskWrapper.java, v 0.1 2014-1-6 ����05:43:26 Exp $ */ public class BasicTaskWrapper implements TaskWrapper { // Constants ----------------------------------------------------- /** The log */ private static final Logger log = Logger.getLogger(BasicTaskWrapper.class); /** The task has not been accepted */ public static final int TASK_NOT_ACCEPTED = 0; /** The task has been accepted */ public static final int TASK_ACCEPTED = 1; /** The task has been started */ public static final int TASK_STARTED = 2; /** The task has completed */ public static final int TASK_COMPLETED = 3; /** The task was rejected */ public static final int TASK_REJECTED = -1; /** The task has been stopped */ public static final int TASK_STOPPED = -2; // Attributes ---------------------------------------------------- /** The state of the task */ private int state = TASK_NOT_ACCEPTED; /** The state lock */ private final Object stateLock = new Object(); /** The task */ private Task task; /** The task as a string */ private String taskString; /** The start time */ private long startTime; /** The start timeout */ private long startTimeout; /** The completion timeout */ private long completionTimeout; /** The priority */ private int priority; /** The wait type */ private int waitType; /** The thread */ private Thread runThread; // Static -------------------------------------------------------- // Constructors -------------------------------------------------- /** * Create a task wrapper without a task */ protected BasicTaskWrapper() { } /** * Create a new task wrapper * * @param task the task * @throws IllegalArgumentException for a null task */ public BasicTaskWrapper(Task task) { setTask(task); } // Public -------------------------------------------------------- // TaskWrapper implementation --------------------------------------- public int getTaskWaitType() { return waitType; } public int getTaskPriority() { return priority; } public long getTaskStartTimeout() { return startTimeout; } public long getTaskCompletionTimeout() { return completionTimeout; } public void acceptTask() { synchronized (stateLock) { // Not in a valid state if (state != TASK_NOT_ACCEPTED) return; } // Accept the task if (taskAccepted()) state = TASK_ACCEPTED; else state = TASK_REJECTED; // Notify the waiting task synchronized (stateLock) { stateLock.notifyAll(); } } public void rejectTask(RuntimeException e) { synchronized (stateLock) { state = TASK_REJECTED; stateLock.notifyAll(); } taskRejected(e); } // Inner classes ------------------------------------------------- public boolean isComplete() { return state == TASK_COMPLETED; } public void stopTask() { boolean started; synchronized (stateLock) { started = (state == TASK_STARTED); state = TASK_STOPPED; } if (started) { // Interrupt the run thread if its not null if (runThread != null) { runThread.interrupt(); } taskStop(); } else if (runThread != null && runThread.isInterrupted()) { /* If the thread has not been returned after being interrupted, then use the deprecated stop method to try to force the thread abort. */ runThread.stop(); } } public void waitForTask() { switch (waitType) { case Task.WAIT_FOR_START: { boolean interrupted = false; synchronized (stateLock) { while (state == TASK_NOT_ACCEPTED || state == TASK_ACCEPTED) { try { stateLock.wait(); } catch (InterruptedException e) { interrupted = true; } } if (interrupted) { Thread.currentThread().interrupt(); } break; } } default: { break; } } } // Runnable implementation --------------------------------------- /** * Called by the thread pool executor */ public void run() { // Get the execution thread this.runThread = Thread.currentThread(); // Check for a start timeout long runTime = getElapsedTime(); if (startTimeout > 0l && runTime >= startTimeout) { taskRejected(new StartTimeoutException("Start Timeout exceeded for task " + taskString)); return; } // We are about to start, check for a stop boolean stopped = false; synchronized (stateLock) { if (state == TASK_STOPPED) { stopped = true; } else { state = TASK_STARTED; taskStarted(); if (waitType == Task.WAIT_FOR_START) stateLock.notifyAll(); } } if (stopped) { taskRejected(new TaskStoppedException("Task stopped for task " + taskString)); return; } // Run the task Throwable throwable = null; try { task.execute(); } catch (Throwable t) { throwable = t; } // It is complete taskCompleted(throwable); // We are completed synchronized (stateLock) { state = TASK_COMPLETED; if (waitType == Task.WAIT_FOR_COMPLETE) stateLock.notifyAll(); } } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- /** * Set thetask for this wrapper * * @param task the task */ protected void setTask(Task task) { if (task == null) throw new IllegalArgumentException("Null task"); this.task = task; this.taskString = task.toString(); this.startTime = System.currentTimeMillis(); this.waitType = task.getWaitType(); this.priority = task.getPriority(); this.startTimeout = task.getStartTimeout(); this.completionTimeout = task.getCompletionTimeout(); } /** * Notify the task it has been accepted * * @return true when the notification succeeds, false otherwise */ protected boolean taskAccepted() { try { task.accepted(getElapsedTime()); return true; } catch (Throwable t) { log.warn("Unexpected error during 'accepted' for task: " + taskString, t); return false; } } /** * Notify the task it has been rejected * * @param e any error associated with the rejection * @return true when the notification succeeds, false otherwise */ protected boolean taskRejected(RuntimeException e) { try { task.rejected(getElapsedTime(), e); return true; } catch (Throwable t) { log.warn("Unexpected error during 'rejected' for task: " + taskString, t); if (e != null) log.warn("Original reason for rejection of task: " + taskString, e); return false; } } /** * Notify the task it has started * * @return true when the notification succeeds, false otherwise */ protected boolean taskStarted() { try { task.started(getElapsedTime()); return true; } catch (Throwable t) { log.warn("Unexpected error during 'started' for task: " + taskString, t); return false; } } /** * Notify the task it has completed * * @param throwable any throwable associated with the completion * @return true when the notification succeeds, false otherwise */ protected boolean taskCompleted(Throwable throwable) { try { task.completed(getElapsedTime(), throwable); return true; } catch (Throwable t) { log.warn("Unexpected error during 'completed' for task: " + taskString, t); if (throwable != null) log.warn("Original error during 'run' for task: " + taskString, throwable); return false; } } /** * Stop the task * * @return true when the notification succeeds, false otherwise */ protected boolean taskStop() { try { task.stop(); return true; } catch (Throwable t) { log.warn("Unexpected error during 'stop' for task: " + taskString, t); return false; } } /** * Calculate the elapsed time since the task was started * * @return the elapsed time in millis */ protected long getElapsedTime() { return System.currentTimeMillis() - startTime; } // Private ------------------------------------------------------- // Inner classes ------------------------------------------------- /** * Get the state as a string * * @return the state string */ protected String getStateString() { switch (state) { case TASK_NOT_ACCEPTED: return "NOT_ACCEPTED"; case TASK_REJECTED: return "REJECTED"; case TASK_ACCEPTED: return "ACCEPTED"; case TASK_STARTED: return "STARTED"; case TASK_STOPPED: return "STOPPED"; case TASK_COMPLETED: return "COMPLETED"; default: return "???"; } } }