package org.googlecode.threadpool; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CentralExecutor implements Executor { private static final Logger LOGGER = LoggerFactory .getLogger(CentralExecutor.class); private static final String CLASS_NAME = CentralExecutor.class .getSimpleName(); public final ExecutorService service; private final Policy policy; private final Map<Class<? extends Runnable>, Submitter> quotas; private final int threadSize; private int reserved; public CentralExecutor(final int threadSize, Policy policy) { this.threadSize = threadSize; this.policy = policy; this.service = Executors.newFixedThreadPool(threadSize, new NamedThreadFactory("jobDispatcher_worker")); this.quotas = new ConcurrentHashMap<Class<? extends Runnable>, Submitter>(); } public CentralExecutor(int threadSize) { this(threadSize, Policy.PESSIMISM); } /** @see ExecutorService#shutdownNow() */ public List<Runnable> shutdownNow() { return service.shutdownNow(); } /** @see ExecutorService#shutdown() */ public void shutdown() { service.shutdown(); } /** @see ExecutorService#isShutdown() */ public boolean isShutdown() { return service.isShutdown(); } /** @see ExecutorService#isTerminated() */ public boolean isTerminated() { return service.isTerminated(); } /** @see ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit) */ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { return service.awaitTermination(timeout, unit); } @Override public void execute(Runnable task) { final Submitter submitter = quotas.get(task.getClass()); if (submitter != null) submitter.submit(task, this); else policy.defaultSubmitter().submit(task, this); } /** @return 预留配额. */ public static Quota reserve(int value) { return new Quota(value); } /** @return 弹性配额. */ public static Quota elastic(int value) { return new Quota(value); } /** @return 零配额. */ public static Quota nil() { return new Quota(0); } /** * 设定taskClass的保留和限制配额. * * @param taskClass * @param reserve * @param elastic * * @throws IllegalArgumentException */ public void quota(Class<? extends Runnable> taskClass, Quota reserve, Quota elastic) { synchronized (this) { if (reserve.getValue() > threadSize - reserved) throw new IllegalArgumentException("No resource for reserve"); reserved += reserve.getValue(); } quotas.put(taskClass, policy.submitter(reserve, elastic)); } public synchronized boolean hasUnreserved() { return threadSize > reserved; } public static class NamedThreadFactory implements ThreadFactory { static final AtomicInteger poolNumber = new AtomicInteger(1); final AtomicInteger threadNumber = new AtomicInteger(1); final ThreadGroup group; final String namePrefix; final boolean isDaemon; public NamedThreadFactory() { this("pool"); } public NamedThreadFactory(String name) { this(name, false); } public NamedThreadFactory(String preffix, boolean daemon) { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread() .getThreadGroup(); namePrefix = preffix + "-" + poolNumber.getAndIncrement() + "-thread-"; isDaemon = daemon; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); t.setDaemon(isDaemon); if (t.getPriority() != Thread.NORM_PRIORITY) { t.setPriority(Thread.NORM_PRIORITY); } return t; } } }