package org.commons.jconfig.internal;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.ThreadSafe;
/**
* Implements a generic executor Service, where class that implement the
* interface worker can be submitted for execution.
* <code>
* WorkerExecutorService executor = new WorkerExecutorService();
* WorkerFuture<String> future = executor.submit(new ReverseStringWorker("12345"));
* String reversedString = future.get();
* executor.shutdown();
* </code>
*
* @author lafa
*
*/
@ThreadSafe
public class WorkerExecutorService {
private final String mName;
private final ExecutorThreadFactory mThreadFactory;
// private final ExecutorThreadFactory mThreadFactoryBoss = new
// ExecutorThreadFactory("async worker boss thread");
private final ExecutorService mScheduler;
// private final ScheduledExecutorService mBossScheduler;
// private final ScheduledFuture<?> bossFuture;
// private final long mDelay;
// private final TimeUnit mUnit;
// private final List<WorkerCallable<?>> mWorkers = new
// CopyOnWriteArrayList<WorkerCallable<?>>();
/**
* Creates a WorkerExecutorService that creates new threads as needed, but
* will reuse previously constructed threads when available.
*/
public WorkerExecutorService(int nThreads) {
this("WorkerExecutorService thread", nThreads);
}
/**
* Creates a WorkerExecutorService that creates new threads as needed, but
* will reuse previously constructed threads when available.
*/
/**
* @param clazz
*/
public WorkerExecutorService(final Class<?> clazz, int nThreads) {
this(clazz.getName(), nThreads);
}
/**
* Creates a WorkerExecutorService that creates new threads as needed, but
* will reuse previously constructed threads when available.
*/
/**
* @param name
*/
public WorkerExecutorService(final String name, int nThreads) {
mName = name;
mThreadFactory = new ExecutorThreadFactory("WorkerExecutorService thread for " + mName);
mScheduler = Executors.newFixedThreadPool(nThreads, mThreadFactory);
}
/**
* Submits a value-returning worker for execution and returns a WorkerFuture
* representing the pending results of the task. The Future's get method
* will return the task's result upon successful completion. If you would
* like to immediately block waiting for a task, you can use constructions
* of the form <code> result = exec.submit(aWorker).get(); </code>
*
* Throws:
*
* RejectedExecutionException - if the worker cannot be scheduled for
* execution
*
* NullPointerException - if the worker is null
*
* @param <V>
* @param worker
* @return
*/
public <V> WorkerFuture<V> submit(final Worker<V> worker) {
Future<V> fut = mScheduler.submit(new WorkerCallable<V>(worker, this));
return new WorkerFutureImpl<V>(fut);
}
/**
* Initiates an shutdown in which previously submitted tasks are executed,
* but no new tasks will be accepted.Invocation has no additional effect if
* already shut down.
*
* Throws:
*
* SecurityException - if a security manager exists and shutting down this
* ExecutorService may manipulate threads that the caller is not permitted
* to modify because it does not hold
* java.lang.RuntimePermission("modifyThread"), or the security manager's
* checkAccess method denies access.
*/
public void shutdown() {
if (mIsShutdown) {
return;
}
mIsShutdown = true;
mScheduler.shutdown();
try {
mScheduler.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// Ignore
}
if (!mScheduler.isShutdown() || !mScheduler.isTerminated()) {
mScheduler.shutdownNow();
try {
mScheduler.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// Ignore
}
}
if (!mScheduler.isShutdown() || !mScheduler.isTerminated()) {
throw new RuntimeException("WorkerExecutorService failed to shutdown.");
}
}
private volatile boolean mIsShutdown = false;
/**
* Returns true if this executor has been shut down.
*
* @return
*/
public boolean isShutdown() {
return mIsShutdown;
}
}