package abra;
import static abra.Logger.log;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Manages threading
*
* @author Lisle E. Mose (lmose at unc dot edu)
*/
public class ThreadManager {
private static final int MAX_PENDING = 100;
private int numThreads;
private List<AbraRunnable> threads = new ArrayList<AbraRunnable>();
private ExecutorService executor;
public ThreadManager(int numThreads) {
this.numThreads = numThreads;
executor = Executors.newFixedThreadPool(numThreads);
}
public void spawnThread(AbraRunnable runnable) {
try {
waitForAvailableThread();
} catch (InterruptedException e) {}
addThread(runnable);
executor.submit(runnable);
}
private synchronized void addThread(AbraRunnable thread) {
threads.add(thread);
}
public synchronized void removeThread(AbraRunnable thread) {
threads.remove(thread);
}
private synchronized int activeThreads() {
return threads.size();
}
private void waitForAvailableThread() throws InterruptedException {
while (activeThreads() >= MAX_PENDING) {
Thread.sleep(50);
}
}
public void waitForAllThreadsToComplete() throws InterruptedException, IOException {
executor.shutdown();
while (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
log("Waiting on " + threads.size() + " threads.");
}
}
public int getNumThreads() {
return numThreads;
}
}