All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ak.trafficController.Task Maven / Gradle / Ivy

Go to download

This deals with different aspects like In memory queue, throttling, event management etc

There is a newer version: 2.1.0
Show newest version
package org.ak.trafficController;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.ak.trafficController.pool.Poolable;

public abstract class Task implements Poolable {
	Logger logger = Logger.getLogger(Task.class.getName());
	protected Task startingTask;
	protected Integer uniqueNumber;
	protected TaskExecutor taskExecutor;
	protected Throwable throwable; //This is for throwing back in case of sync tasks and any task throw exception.

	protected String name;
	
	protected Task parentTask; //The task which is parent of this sub chain.
	
	public enum TaskType {
		SLOW, NORMAL, NOTIFY
	}
	protected TaskType taskType;
	protected Task nextTask;
	protected Task exceptionTask;
	private boolean shouldThrowException;
	protected boolean shouldContinueOnException;
	
	/* (non-Javadoc)
	 * @see org.ak.trafficController.pool.Poolable#clean()
	 */
	@Override
	public void clean() {
		logger.finer("about to clean up " + this.name + " " + this.hashCode() + " " + this.getClass() + " " + this.taskType + " for " + uniqueNumber + getStackTrace());
		taskType = null;
		startingTask = null;
		nextTask = null;
		uniqueNumber = null;
	}
	
	/**
	 * Returns the stack trace for debug purposes.
	 * @return Stack trace as string
	 */
	private String getStackTrace() {
		StringBuilder sb = new StringBuilder();
		for(StackTraceElement ste : Thread.currentThread().getStackTrace()) {
			sb.append(ste.getClassName()).append(" ").append(ste.getLineNumber()).append(",");
		}
		return sb.toString();
	}

	/**
	 * The current task is executed by this method. For each type of task it will behave differently.
	 * @throws Throwable In case any exception occurred in task, a Throwable will be thrown
	 */
	abstract protected void executeCurrentTask() throws Throwable;
	
	/**
	 * Constructor of Task to keep every task defined as a unique number and a given task type.
	 * @param unique Unique id
	 * @param taskType Task type
	 */
	public Task(int unique,TaskType taskType) {
		startingTask = this;
		this.taskType = taskType;
		this.uniqueNumber = unique;
	}
	
	/**
	 * This method is controlling the behavior of most of the tasks.
	 * We will execute current task and then execute next task (mostly adding to TaskExecutor)
	 * @throws Throwable Throws if any issue occur in processing task
	 */
	protected void executeInternal() throws Throwable {
		executeCurrentTask();
		executeNextTask();
	}
	
	/**
	 * This method is called from task executor for running the task.
	 * We try to handle the exception which if occur we throw the same to user.
	 */
	protected void execute() {
		try {
			executeInternal();
		} catch (Throwable throwable) {
			handleException(throwable);
		}
	}

	/**
	 * This method handles the exception scenario.
	 * This method is responsible for throwing exception if configured or not throw if not configured.
	 * Any task can have a exception handler which can handle the exception.
	 * If the exception is handled by exception handler and it is configured to continue post catching, next tasks are continued.
	 * Else Next tasks are not executed.
	 * It throws exception if either we have not attached a exception handler or we have configured task to throw exception even after handling.
	 * @param throwable It throws exception if either we have not attached a exception handler or we have configured task to throw exception even after handling 
	 */
	protected void handleException(Throwable throwable) {
		logger.log(Level.WARNING, "Exception occured in executing a task", throwable);
		this.throwable = throwable;
		boolean shouldThrow = false;
		if (Objects.isNull(exceptionTask)) {
			shouldThrow = true;
		}
		else {
			shouldThrow = this.shouldThrowException;
			this.exceptionTask.execute();
		}
		if (!shouldThrow && shouldContinueOnException) {
			executeNextTask();
			return;
		}
		
		throwIfRequired(throwable, shouldThrow);
	}

	/**
	 * This method configures to throw the exception.
	 * Throwing of exception is handled by Notify Task which is the last task and has responsibility to awake user back.
	 * If we have submitted a request and not called for start, we do not throw the exception, just log the exception.
	 * This method also cleans up all other tasks pending to be executed in the task chain.
	 * @param throwable Throwable which will be thrown
	 * @param shouldThrow If set then Notify task will be configured to throw the exception
	 */
	protected void throwIfRequired(Throwable throwable, boolean shouldThrow) {
		Task task = this;
		while (!Objects.isNull(task.nextTask)) {
			task = task.nextTask;
		}
		if (task.taskType == TaskType.NOTIFY) {
			if (shouldThrow) {
				task.throwable = throwable;
			} //won't set throwable if already handled.
			task.execute();
		}
		cleanAllRemainingTasks();
	}

	/**
	 * Configure a task to throw exception if occurs even after handling it.
	 * @return Self to continue modification easily
	 */
	public Task shouldThrowExceptionIfOccurs() {
		this.shouldThrowException = true;
		return this;
	}
	
	/**
	 * Configure a task to continue next task if exception handler is present.
	 * @return Self to continue modification easily
	 */
	public Task shouldContinueNextTaskIfExceptionOccurs() {
		this.shouldContinueOnException = true;
		return this;
	}
	
	/**
	 * This method cleans all remaining tasks.
	 */
	protected void cleanAllRemainingTasks() {
		List tasks = new ArrayList<>(); 
		Task task = this;
		while (!Objects.isNull(task.nextTask)) {
			tasks.add(task);
			task = task.nextTask;
		}
		for (Task t : tasks) {
			t.nextTask = null;
		}
		tasks.clear();
	}

	/**
	 * This method executes next next thread and for doing so calls task executor to call next task.
	 * Also if we can pool the task, we pool it back to save creation time.
	 */
	protected void executeNextTask() {
		if (nextTask != null) {
			if (nextTask.taskExecutor == null) {
				nextTask.taskExecutor = taskExecutor;
			}
			nextTask.taskExecutor.enque(nextTask);
		}
		if (canSendBackToPool()) {
			this.addBackToPool();
		}
	}
	
	/**
	 * Configures if current task be sent back to pool.
	 * @return true if configured to send back to pool
	 */
	public boolean canSendBackToPool() {
		return this.startingTask != this;
	}

	/**
	 * This will start the execution and calling thread will wait for execution.
	 * Throwable is thrown if any task execution throws any exception. The user can also handle the exception by adding onException method call.
	 * @param timeToWait Max time we will wait for the response.
	 * @throws Throwable Throwable is thrown if any method execution fails
	 */
	public void start(long timeToWait) throws Throwable {
		NotifyingTask task = new NotifyingTask(uniqueNumber);
		then(task);
		doSubmit();
		pauseExecutingThread(task, timeToWait);
	}
	
	/**
	 * This is default start where we are waiting for 5 minutes to complete of a task chain.
	 * @throws Throwable Throwable is thrown if any method execution fails
	 */
	public void start() throws Throwable {
		start(5*60*60);
	}
	
	/**
	 * Attaching exception handler. We can have a chain of processes which may be required post handling the exception.
	 * To return back to normal task to which we attached the exception handler please use {@link Task#getParentTask()}. 
	 * @param exceptionHandler Exception handler which will handle the exception
	 * @return Exceutable task, the exception handler task
	 */
	public ExecutableTask onException(Consumer exceptionHandler) {
		RunnableToBeExecuted runnable = ()-> exceptionHandler.accept(this.throwable);
		ExecutableTask task = ExecutableTask.getFromPool(uniqueNumber,runnable, TaskType.NORMAL);
		setExceptionTaskParams(task);
		return task;
	}
	
	/**
	 * Attaching exception handler which will also thought of returning some value which can be processed by next task.
	 * We can have a chain of processes which may be required post handling the exception.
	 * To return back to normal task to which we attached the exception handler please use {@link Task#getParentTask()}.
	 * @param exceptionHandler Exception handler function
	 * @param  function return type
	 * @return Returning Task
	 */
	public  ReturningTask onExceptionGet(Function exceptionHandler) {
		SupplierWhichCanThrowException supplier = ()->exceptionHandler.apply(throwable);
		ReturningTask task = ReturningTask.getFromPool(uniqueNumber, supplier, TaskType.NORMAL);
		setExceptionTaskParams(task);
		return task;
	}
	
	/**
	 * This method add exception handler and also configure to continue post handling the exception.
	 * We can have a chain of processes which may be required post handling the exception.
	 * To return back to normal task to which we attached the exception handler please use {@link Task#getParentTask()}.
	 * @param exceptionHandler Exception handler
	 * @return Executable task
	 */
	public ExecutableTask onExceptionPerfomAndAlsoContinueOtherTasks(Consumer exceptionHandler) {
		RunnableToBeExecuted runnable = ()-> exceptionHandler.accept(this.throwable);
		ExecutableTask task = ExecutableTask.getFromPool(uniqueNumber,runnable, TaskType.NORMAL);
		setExceptionTaskParams(task);
		task.shouldContinueOnException = true;
		return task;
	}
	
	/**
	 * This method add exception handler and also configure to continue post handling the exception.
	 * We can have a chain of processes which may be required post handling the exception.
	 * To return back to normal task to which we attached the exception handler please use {@link Task#getParentTask()}.
	 * @param exceptionHandler Exception handler function
	 * @param  type of function return type
	 * @return Returning task
	 */
	public  ReturningTask onExceptionGetAndAlsoContinueOtherTasks(Function exceptionHandler) {
		SupplierWhichCanThrowException supplier = ()->exceptionHandler.apply(throwable);
		ReturningTask task = ReturningTask.getFromPool(uniqueNumber, supplier, TaskType.NORMAL);
		setExceptionTaskParams(task);
		
		return task;
	}

	/**
	 * This method configures the exception task and current task to maintain the task chains.
	 * @param task Exception task
	 */
	protected void setExceptionTaskParams(Task task) {
		task.parentTask = this;
		this.exceptionTask = task;
		task.taskExecutor = taskExecutor;
	}
	
	
	/**
	 * In case we have started an operation, we need to wait till the operation completes.
	 * The caller thread will wait here for specified time or if task completes.
	 * Notify task is used to notify the current task as monitor.  
	 * @param task Notify task
	 * @param timeToWait Max Time for which we need to wait.
	 * @throws Throwable Throws exception if any exception occured in processing or timed out
	 */
	protected void pauseExecutingThread(NotifyingTask task, long timeToWait) throws Throwable {
		synchronized(task) {
			try {
				task.wait(timeToWait);
			} catch (InterruptedException e) {
				logger.log(Level.WARNING, "could not wait....", e);
			}
			
			if (!Objects.isNull(task.throwable)) {
				throw task.throwable;
			}
		
			if (!task.executed) {
				throw new RuntimeException("Could not process in time");
			}
		}
	}

	/**
	 * Submit means just add the tasks and forget about the processing. It will be processed in same priority and using same task executor but use do not need to wait for completion of task.
	 */
	public void submit() {
		doSubmit();
	}

	/**
	 * This starts the current task chain.
	 */
	protected void doSubmit() {
		Task task;
		if (Objects.isNull(this.parentTask)) {
			task = this.startingTask;
		} else {
			task = this.parentTask;
			while (!Objects.isNull(task.parentTask)) {
				task = task.parentTask;
			}
			task = task.startingTask;
		}
		try {
		taskExecutor.enque(task);
		} catch (Exception e) {
			System.err.println(this);
			e.printStackTrace();
		}
	}
	
	/**
	 * This method add a task to the chain.
	 * @param task Task which needs to be added to next chain.
	 * @return the chained task
	 */
	public Task then(Task task) {
		Task lastTask = this;
		while (lastTask.nextTask != null) {
			lastTask = lastTask.nextTask;
		}
		lastTask.nextTask = task;
		task.startingTask = this.startingTask;
		task.uniqueNumber = this.uniqueNumber;
		task.taskExecutor = this.taskExecutor;
		task.parentTask = lastTask.parentTask;
		return task;
	}
	
	/**
	 * This method add a new task in chain which will be run post running current task which will be running the supplier and data can be used further as configured in next tasks.
	 * This creates {@link ReturningTask} which can be then 
	 * 
  • used to consume the data by using {@link ReturningTask#thenConsume(Consumer)} or {@link ReturningTask#thenConsumeMultiple(Consumer...)}.
  • *
  • used to further create new task which will work on this data and return something else by using {@link ReturningTask#then(Function)}.
  • *
* @param supplier Supplier which will be run post the execution of current task * @param Supplier type * @return Returning task */ public ReturningTask then(SupplierWhichCanThrowException supplier) { ReturningTask task = ReturningTask.getFromPool(uniqueNumber, supplier, TaskType.NORMAL); then(task); return task; } /** * This method creates a new task for the given runnable which will be added to the task chain. * @param runnable Runnable to be executed post the current task * @return Executable task */ public Task then(RunnableToBeExecuted runnable) { ExecutableTask task = ExecutableTask.getFromPool(uniqueNumber,runnable, TaskType.NORMAL); then(task); return task; } /** * This method is similar to {@link Task#then(SupplierWhichCanThrowException)} with a difference that new task will be treated as slow task. * @param supplier Supplier to be executed in this new task * @param Supplier type * @return Returning Task */ public ReturningTask thenSlow(SupplierWhichCanThrowException supplier) { ReturningTask task = ReturningTask.getFromPool(uniqueNumber,supplier, TaskType.SLOW); then(task); return task; } /** * This method is similar to {@link Task#then(RunnableToBeExecuted)} with a difference that new task will be treated as slow task. * @param runnable Runnable to be executed in this new task * @return Executable task */ public Task thenSlow(RunnableToBeExecuted runnable) { ExecutableTask task = ExecutableTask.getFromPool(uniqueNumber, runnable, TaskType.SLOW); then(task); return task; } /** * There can be a scenario where we want items of collection to be consumed in parallel. * This method will create such task which will be added next to current task. * @param tp Task type * @param collection Collection to be worked on * @param consumerToWorkOn Consumer Consumer of each item in Collection * @param Supplier type * @return ParallelExecuting Task */ public ParallelExecutingTask thenParallel(TaskType tp, Collection collection, Consumer consumerToWorkOn) { int size = 0; if (!Objects.isNull(collection)) { size = collection.size(); } RunnableToBeExecuted[] runnables = new RunnableToBeExecuted[size]; if (size > 0) { int i =0; for (T item : collection) { runnables[i++] = ()-> consumerToWorkOn.accept(item); } } return thenParallelWithoutWait(tp, runnables); } /** * This method helps for a requirement where we want to work on same data in different consumers in parallel. * Consider you have a data which needs to be added to cache as well as to database etc. * Or consider you have a data for which you want to update multiple tables or work on different sqls in parallel. * This task will help doing the things concurrently. * This task will be added next to the data. * @param tp Task type * @param itemToWorkOn Item which needs to be worked upon * @param consumersToWorkOn Consumers which will be executed * @param Supplier type * @return Parallel Executing task */ public ParallelExecutingTask thenParallel(TaskType tp, T itemToWorkOn, Collection> consumersToWorkOn) { int size = 0; if (!Objects.isNull(consumersToWorkOn)) { size = consumersToWorkOn.size(); } RunnableToBeExecuted[] runnables = new RunnableToBeExecuted[size]; if (size > 0) { int i =0; for (Consumer consumer : consumersToWorkOn) { runnables[i++] = ()-> consumer.accept(itemToWorkOn); } } return thenParallel(tp, runnables); } /** * There can be a scenario where we want items of collection to be consumed in parallel. * This method will create such task which will be added next to current task. * This new task will run in Async mode. * Returning back to normal chain will need {@link Task#getParentTask()} * @param tp Task type * @param collection Collection to be worked on * @param consumerToWorkOn Consumer Consumer of each item in Collection * @param Collection and consumer type * @return ParallelExecuting Task */ public ParallelExecutingTask thenParallelAsync(TaskType tp, Collection collection, Consumer consumerToWorkOn) { int size = 0; if (!Objects.isNull(collection)) { size = collection.size(); } RunnableToBeExecuted[] runnables = new RunnableToBeExecuted[size]; if (size > 0) { int i =0; for (T item : collection) { runnables[i++] = ()-> consumerToWorkOn.accept(item); } } return thenParallelWithoutWait(tp, runnables); } /** * This method helps for a requirement where we want to work on same data in different consumers in parallel. * Consider you have a data which needs to be added to cache as well as to database etc. * Or consider you have a data for which you want to update multiple tables or work on different sqls in parallel. * This task will help doing the things concurrently. * The data created in this by different consumers can be merged using {@link ParallelReturningTask#join(Consumer)} or {@link ParallelReturningTask#join(Function)} * This task will be added next to the data. * This new task will run in Async mode. * Returning back to normal chain will need {@link Task#getParentTask()} * @param tp Task type * @param itemToWorkOn Item to be worked on * @param functions Functions to be run on the data in parallel * @param Function return type * @param Type of item to work on * @return Parallel Returning task */ public ParallelReturningTask thenParallelReturning(TaskType tp, K itemToWorkOn, Collection> functions) { Supplier suppliers[] = new Supplier[functions.size()]; int i = 0; for (Function function : functions) { suppliers[i++] = ()->function.apply(itemToWorkOn); } return thenParallel(tp, suppliers); } /** * This method helps for a requirement where we want to work on same data in different consumers in parallel. * Consider you have a data which needs to be added to cache as well as to database etc. * Or consider you have a data for which you want to update multiple tables or work on different sqls in parallel. * This task will help doing the things concurrently. * The data created in this by different consumers can be merged using {@link ParallelReturningTask#join(Consumer)} or {@link ParallelReturningTask#join(Function)} * This task will be added next to the data. * @param tp Task type * @param itemToWorkOn Item to be worked on * @param functions Functions to be run on the data in parallel * @param Function return type * @param Type of item to work on * @return Parallel Returning task */ public ParallelReturningTask thenParallelReturningAsync(TaskType tp, K itemToWorkOn, Collection> functions) { Supplier suppliers[] = new Supplier[functions.size()]; int i = 0; for (Function function : functions) { suppliers[i++] = ()->function.apply(itemToWorkOn); } return thenParallelWithoutWait(tp, suppliers); } /** * This method helps for a requirement where we want to work on same data in different consumers in parallel. * Consider you have a data which needs to be added to cache as well as to database etc. * Or consider you have a data for which you want to update multiple tables or work on different sqls in parallel. * This task will help doing the things concurrently. * This task will be added next to the data. * This new task will run in Async mode. * Returning back to normal chain will need {@link Task#getParentTask()} * @param tp Task type * @param itemToWorkOn Item which needs to be worked upon * @param consumersToWorkOn Consumers which will be executed * @param Type of item to work on * @return Parallel Executing task */ public ParallelExecutingTask thenParallelAsync(TaskType tp, T itemToWorkOn, Collection> consumersToWorkOn) { int size = 0; if (!Objects.isNull(consumersToWorkOn)) { size = consumersToWorkOn.size(); } RunnableToBeExecuted[] runnables = new RunnableToBeExecuted[size]; if (size > 0) { int i =0; for (Consumer consumer : consumersToWorkOn) { runnables[i++] = ()-> consumer.accept(itemToWorkOn); } } return thenParallelWithoutWait(tp, runnables); } /** * This method create a task with runnables to be run in parallel (In ParallelExecutingTask) which will be run separately. * Execution of current task will just add this task to the executor pool and won't wait for its completion and will start working on its next task. * Other tasks can be added to this task but will not be coupled with original task chain. * To add new task in original task chain, please use {@link Task#getParentTask()}. * @param tp Task type * @param runnables Runnables to be run * @return Parallel Executing task */ public ParallelExecutingTask thenParallelWithoutWait(TaskType tp, RunnableToBeExecuted... runnables) { ParallelExecutingTask parallelExecutingTask = ParallelExecutingTask.getFromPool(uniqueNumber, tp, runnables); UnlinkedTask task = new UnlinkedTask(uniqueNumber, tp, parallelExecutingTask); includeUnlinkTask(parallelExecutingTask, task); return parallelExecutingTask; } /** * This method create a task with runnables to be run in parallel (In ParallelExecutingTask) which will be run separately. * Execution of current task will just add this task to the executor pool and won't wait for its completion and will start working on its next task. * Other tasks can be added to this task but will not be coupled with original task chain. * To add new task in original task chain, please use {@link Task#getParentTask()}. * In this method, task executor is also accepted in which this new task will be executed. * @param tp Task type * @param taskExecutor Task executor where this new task will run * @param runnables Runnables * @return Parallel Executing Task */ public ParallelExecutingTask thenParallelWithoutWait(TaskType tp, TaskExecutor taskExecutor, RunnableToBeExecuted... runnables) { ParallelExecutingTask parallelExecutingTask = ParallelExecutingTask.getFromPool(uniqueNumber, tp, runnables); UnlinkedTask task = new UnlinkedTask(uniqueNumber, tp, parallelExecutingTask) .setTaskExecutorForAsyncTask(taskExecutor); includeUnlinkTask(parallelExecutingTask, task); parallelExecutingTask.taskExecutor = taskExecutor; return parallelExecutingTask; } /** * Include unlink task. * @param parallelExecutingTask Task which will be run async * @param task The unlink task which will add the parallelExecutingTask in executor. */ protected void includeUnlinkTask(Task parallelExecutingTask, UnlinkedTask task) { then(task); parallelExecutingTask.taskExecutor = taskExecutor; } /** * * This method create a task with runnables to be run in parallel (In ParallelExecutingTask) which will be run separately. * Execution of current task will just add this task to the executor pool and won't wait for its completion and will start working on its next task. * Other tasks can be added to this task but will not be coupled with original task chain. * To add new task in original task chain, please use {@link Task#getParentTask()}. * @param runnables Runnables * @return ParallelExecutingTask */ public ParallelExecutingTask thenParallelWithoutWait(RunnableToBeExecuted... runnables) { return thenParallelWithoutWait(TaskType.NORMAL, runnables); } /** * * This method create a task with runnables to be run in parallel (In ParallelExecutingTask) which will be run separately. * Execution of current task will just add this task to the executor pool and won't wait for its completion and will start working on its next task. * Other tasks can be added to this task but will not be coupled with original task chain. * To add new task in original task chain, please use {@link Task#getParentTask()}. * The task will be a slow task. * @param runnables Runnables * @return Parallel Executing Task */ public ParallelExecutingTask thenParallelWithoutWaitSlow(RunnableToBeExecuted... runnables) { return thenParallelWithoutWait(TaskType.SLOW, runnables); } /** * This method creates a task which will run multiple runnables in parallel. * Once all task of runnables completes, then only another task which can be added by using methods in {@link ParallelExecutingTask}. * @param runnables Runnables * @return Parallel Executing task */ public ParallelExecutingTask thenParallel(RunnableToBeExecuted... runnables) { return thenParallel(TaskType.NORMAL, runnables); } /** * This method creates a task which will run multiple runnables in parallel. * Once all task of runnables completes, then only another task which can be added by using methods in {@link ParallelExecutingTask}. * @param tp Task type * @param runnables Runnables * @return Parallel Executing Task */ public ParallelExecutingTask thenParallel(TaskType tp, RunnableToBeExecuted... runnables) { ParallelExecutingTask parallelExecutingTask = ParallelExecutingTask.getFromPool(uniqueNumber, tp, runnables); then(parallelExecutingTask); return parallelExecutingTask; } /** * This method creates a task which is actually having multiple suppliers. These suppliers will run in parallel * and can be joined by using {@link ParallelReturningTask#join(Consumer)} or {@link ParallelReturningTask#join(Function)} * @param suppliers Suppliers * @param Supplier type * @return Parallel Returning task */ public ParallelReturningTask thenParallel(Supplier... suppliers) { ParallelReturningTask parallelExecutingTask = thenParallel(TaskType.NORMAL, suppliers); return parallelExecutingTask; } /** * This method creates a task which is actually having multiple suppliers. These suppliers will run in parallel * and can be joined by using {@link ParallelReturningTask#join(Consumer)} or {@link ParallelReturningTask#join(Function)}. * @param tp Task type * @param suppliers Suppliers * @param Supplier type * @return ParallelRetruning task */ public ParallelReturningTask thenParallel(TaskType tp, Supplier... suppliers) { ParallelReturningTask parallelExecutingTask = ParallelReturningTask.getFromPool(uniqueNumber,tp,suppliers); then(parallelExecutingTask); return parallelExecutingTask; } /** * This method creates a task which is actually having multiple suppliers. These suppliers will run in parallel * and can be joined by using {@link ParallelReturningTask#join(Consumer)} or {@link ParallelReturningTask#join(Function)}. * This task runs in async mode. To return back to original task, please use {@link Task#getParentTask()}. * @param tp Task type * @param suppliers Suppliers * @param Supplier type * @return ParallelRetruning task */ public ParallelReturningTask thenParallelWithoutWait(TaskType tp, Supplier... suppliers) { ParallelReturningTask parallelReturningTask = ParallelReturningTask.getFromPool(uniqueNumber,tp,suppliers); UnlinkedTask task = new UnlinkedTask(uniqueNumber, tp, parallelReturningTask); includeUnlinkTask(parallelReturningTask, task); return parallelReturningTask; } /** * This method creates a task which will run multiple runnables in parallel. * Once all task of runnables completes, then only another task which can be added by using methods in {@link ParallelExecutingTask}. * This will be slow task. All runnables will be treated to be run as slow task. * @param runnables Runnables * @return Parallel Executing task */ public ParallelExecutingTask thenParallelSlow(RunnableToBeExecuted... runnables) { return thenParallel(TaskType.SLOW, runnables); } /** * This method creates a task which is actually having multiple suppliers. These suppliers will run in parallel * and can be joined by using {@link ParallelReturningTask#join(Consumer)} or {@link ParallelReturningTask#join(Function)}. * This will be a slow task and all suppliers will run as slow task. * @param suppliers Suppliers * @param Supplier type * @return ParallelRetruning task */ public ParallelReturningTask thenParallelSlow(Supplier... suppliers) { return thenParallel(TaskType.SLOW, suppliers); } /** * This adds task chain a way to have sub task of a task. The parent denotes the parent task of the branched chain. * @return Parent task */ public Task getParentTask() { return this.parentTask; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return name + " Task [type: " + this.getClass() + ", uniqueNumber: " + uniqueNumber + ", taskType : " + taskType + "]"; } public TaskExecutor getTaskExecutor() { return taskExecutor; } public Task getStartTask() { return this.startingTask; } public String getName() { return name; } /** * Set name of the task. This helps for diagnostics. * @param name Name of the task * @return Self to ease modification */ public Task setName(String name) { this.name = name; return this; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy