001package com.mrivanplays.process; 002 003import java.util.concurrent.Executor; 004import java.util.concurrent.ExecutorService; 005import java.util.concurrent.Executors; 006import java.util.concurrent.ThreadFactory; 007import java.util.concurrent.atomic.AtomicInteger; 008 009/** 010 * Represents a scheduler of {@link Process Processes}. 011 * 012 * @since 0.0.1 013 * @author <a href="mailto:[email protected]">Ivan Pekov</a> 014 */ 015public final class ProcessScheduler { 016 017 private final Executor async; 018 private final ExecutorService service; 019 020 /** Create a new {@code ProcessScheduler} which also creates a new {@link ExecutorService} */ 021 public ProcessScheduler() { 022 this( 023 Executors.newCachedThreadPool( 024 new ThreadFactory() { 025 026 private AtomicInteger count = new AtomicInteger(0); 027 028 @Override 029 public Thread newThread(Runnable r) { 030 Thread thread = new Thread(r); 031 thread.setName("ProcessScheduler Thread #" + count.getAndIncrement()); 032 return thread; 033 } 034 })); 035 } 036 037 /** 038 * Create a new {@code ProcessScheduler} 039 * 040 * @param async executor in which processes are executed 041 */ 042 public ProcessScheduler(Executor async) { 043 this.async = async; 044 this.service = async instanceof ExecutorService ? (ExecutorService) async : null; 045 } 046 047 /** 048 * Runs all the specified {@link Process} {@code processes} whilst also returning a {@link 049 * ProcessesCompletion}. 050 * 051 * @param processes the processes to run 052 * @return a process completion 053 * @see Process 054 * @see ProcessesCompletion 055 */ 056 public ProcessesCompletion runProcesses(Process... processes) { 057 ProcessesCompletion ret = new ProcessesCompletion(processes.length, this.async); 058 for (int i = 0; i < processes.length; i++) { 059 int processNum = i + 1; 060 Process process = processes[i]; 061 this.async.execute( 062 () -> { 063 process.processNum(processNum); 064 process.runProcess(ret); 065 }); 066 } 067 return ret; 068 } 069 070 /** 071 * Runs all the specified {@link ResultedProcess} whilst also returning a {@link 072 * ResultedProcessesCompletion}. 073 * 074 * @param processes the resulted processes to run 075 * @return a process completion 076 * @param <T> result value type parameter 077 * @see ResultedProcess 078 * @see ResultedProcessesCompletion 079 */ 080 @SafeVarargs 081 public final <T> ResultedProcessesCompletion<T> runProcesses(ResultedProcess<T>... processes) { 082 ResultedProcessesCompletion<T> ret = 083 new ResultedProcessesCompletion<>(processes.length, this.async); 084 for (ResultedProcess<T> process : processes) { 085 this.async.execute(() -> process.runProcess(ret)); 086 } 087 return ret; 088 } 089 090 /** 091 * If an {@link ExecutorService} has been created/detected whilst this {@code ProcessScheduler} 092 * was created, this will call it's {@link ExecutorService#shutdown()} method. 093 */ 094 public void shutdownExecutorService() { 095 if (this.service != null) { 096 this.service.shutdown(); 097 } 098 } 099}