package proj.zoie.api;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import proj.zoie.api.impl.ZoieContext;
/**
* This class provides the thread pools that can understand Zoie's threadlocal context.
* The worker thread will run the task in the ZoieContext that is the same as that of
* the submitting thread at the job submitting time. If the ZoieContext for the submitting
* thread has changed since the submission time before the task is run, the change in
* the submitting thread does not affect the worker thread. If the worker thread's action
* causes the ZoieContext to change, the change would not affect the submitting thread's
* ZoieContext. Using the thread pools from this class will allow transparent multi-threading
* for Zoie.
* @author "Xiaoyang Gu<xgu@linkedin.com>"
*
*/
public class ZoieThreadPoolExecutor extends ThreadPoolExecutor {
public ZoieThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
public ZoieThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
}
public ZoieThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
}
public ZoieThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
ZoieContext.getContext().clear();
super.afterExecute(((ZoieRunnable) r).innerRunnable, t);
}
/*
* (non-Javadoc)
* @see java.util.concurrent.ThreadPoolExecutor#beforeExecute(java.lang.Thread,
* java.lang.Runnable)
*/
@Override
protected void beforeExecute(Thread t, Runnable r) {
if (!(r instanceof ZoieRunnable)) throw new RuntimeException(
"Not a properly submitted zoie job");
ZoieContext.setContext(((ZoieRunnable) r).ctx);
super.beforeExecute(t, ((ZoieRunnable) r).innerRunnable);
}
@Override
public void execute(Runnable command) {
super.execute(new ZoieRunnable(command));
}
protected static class ZoieRunnable implements Runnable {
private final Runnable innerRunnable;
private final ZoieContext ctx;
/**
* Get the current thread's ZoieContext to keep in the wrapper runnable so that
* when the runnable is executed, the context can be set to be the same as the
* invoking thread.
* @param runnable
*/
public ZoieRunnable(Runnable runnable) {
innerRunnable = runnable;
ctx = ZoieContext.getContext();
}
public ZoieContext getContext() {
return ctx;
}
public void run() {
innerRunnable.run();
}
}
}