code: package dotnet54.classifiers.knn;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  import java.util.concurrent.*;
  
  public class AsyncTasks<T> {
  
  	private ExecutorService executor;
  	protected int numThreads;
  
  	public AsyncTasks(int numThreads) {
  		if (numThreads == 0) { // auto
  			numThreads = Runtime.getRuntime().availableProcessors();
  		}
  		this.numThreads = numThreads;
  		setExecutor(Executors.newFixedThreadPool(numThreads));
  	}
  
  	public ExecutorService getExecutor() {
  		return executor;
  	}
  
  	public void setExecutor(ExecutorService executor) {
  		this.executor = executor;
  	}
  
  	public ThreadPoolExecutor getThreadPool() {
  		if (executor instanceof ThreadPoolExecutor) {
  			return ((ThreadPoolExecutor) executor);
  		} else {
  			return null;
  		}
  	}
  
  //	public class AsyncTaskResult{
  //		protected AtomicInteger taskID;
  //
  //		public AsyncTaskResult(int taskID){
  //			this.taskID = new AtomicInteger(taskID);
  //		}
  //
  //		public AtomicInteger getTaskID() {
  //			return taskID;
  //		}
  //	}
  //
  //	public class AsyncTask implements Callable<T>{
  //		protected int taskID;
  //		protected T result;
  //
  //		public AsyncTask(int taskID){
  //			this.taskID = taskID;
  //		}
  //
  //		@Override
  //		public T call() throws Exception {
  //			return result;
  //		}
  //	}
  
  	public List<T> run(Callable<T>[] tasks) throws InterruptedException, ExecutionException {
  		List<Callable<T>> taskList = Arrays.asList(tasks);
  		List<Future<T>> futures;
  		List<T> results = new ArrayList<>(tasks.length);
  		futures = this.executor.invokeAll(taskList);
  
  		for (int i = 0; i < futures.size(); i++) {
  			Future<T> result = futures.get(i);
  			results.add(result.get()); //dev
  		}
  		return results;
  	}
  
  }
  