import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.log4j.Logger; /** * <pre> * 分级事件驱动架构SEDA( Staged E ventDriven A rch itecture)的构造类 * @author kanpiaoxue * @param <Task> SEDAThreadPoolUtils内置的 interface Task * 2013-11-07 * </pre> */ public final class SEDAThreadPool { private static final Logger LOGGER = Logger.getLogger(SEDAThreadPool.class); private final BlockingQueue<SEDAThreadPool.Task> inputQueue; private final BlockingQueue<SEDAThreadPool.Task> outputQueue; private final ExecutorService exec; private final String threadName; private final int threadPoolSize; private final ConcurrentHashMap<SEDAThreadPool.Task, SEDAThreadPool.Task> conflictMap; private volatile boolean hasOutput; private volatile boolean hasConflictMap; /** * <pre> * @param threadName 工作线程的名称 * @param inputQueue 输入任务的队列 * @param outputQueue 输出任务的队列。当不存在输出队列是,该项可以为 null * @param exec 执行的线程池。如果该项为 null,则采用默认的 Executors.newCachedThreadPool() * @param threadPoolSize 线程池的大小 * </pre> */ public SEDAThreadPool(String threadName, BlockingQueue<Task> inputQueue, BlockingQueue<Task> outputQueue, ExecutorService exec, int threadPoolSize) { this(threadName, inputQueue, outputQueue, exec, threadPoolSize, null); } /** * <pre> * @param threadName 工作线程的名称 * @param inputQueue 输入任务的队列 * @param exec 执行的线程池。如果该项为 null,则采用默认的 Executors.newCachedThreadPool() * @param threadPoolSize 线程池的大小 * </pre> */ public SEDAThreadPool(String threadName, BlockingQueue<Task> inputQueue, ExecutorService exec, int threadPoolSize) { this(threadName, inputQueue, null, exec, threadPoolSize, null); } /** * <pre> * @param threadName 工作线程的名称 * @param inputQueue 输入任务的队列 * @param exec 执行的线程池。如果该项为 null,则采用默认的 Executors.newCachedThreadPool() * @param threadPoolSize 线程池的大小 * @param conflictMap Task发生冲突Map :和 conflictMap 中的key存在冲突的任务都不会被执行 * </pre> */ public SEDAThreadPool( String threadName, BlockingQueue<Task> inputQueue, ExecutorService exec, int threadPoolSize, ConcurrentHashMap<SEDAThreadPool.Task, SEDAThreadPool.Task> conflictMap) { this(threadName, inputQueue, null, exec, threadPoolSize, conflictMap); } /** * <pre> * @param threadName 工作线程的名称 * @param inputQueue 输入任务的队列 * @param outputQueue 输出任务的队列。当不存在输出队列是,该项可以为 null * @param exec 执行的线程池。如果该项为 null,则采用默认的 Executors.newCachedThreadPool() * @param threadPoolSize 线程池的大小 * @param conflictMap Task发生冲突Map :和 conflictMap 中的key存在冲突的任务都不会被执行 * </pre> */ public SEDAThreadPool( String threadName, BlockingQueue<SEDAThreadPool.Task> inputQueue, BlockingQueue<SEDAThreadPool.Task> outputQueue, ExecutorService exec, int threadPoolSize, ConcurrentHashMap<SEDAThreadPool.Task, SEDAThreadPool.Task> conflictMap) { super(); this.threadName = threadName; this.inputQueue = inputQueue; this.outputQueue = outputQueue; this.exec = (null == exec) ? Executors.newCachedThreadPool() : exec; this.threadPoolSize = threadPoolSize; this.conflictMap = conflictMap; if (null != conflictMap) { hasConflictMap = true; } this.hasOutput = (null != outputQueue); } /** * <pre> * 创建SEDA线程池 * </pre> */ public void createSEDAThreadPool() { for (int i = 0; i < threadPoolSize; i++) { exec.execute(new InnerConsumer(threadName + i, inputQueue, outputQueue)); } } private class InnerConsumer implements Runnable { private final String name; private final BlockingQueue<SEDAThreadPool.Task> inputQueue; private final BlockingQueue<SEDAThreadPool.Task> outputQueue; public InnerConsumer(String name, BlockingQueue<SEDAThreadPool.Task> inputQueue, BlockingQueue<SEDAThreadPool.Task> outputQueue) { super(); this.name = name; this.inputQueue = inputQueue; this.outputQueue = outputQueue; } @Override public void run() { Thread.currentThread().setName(name); if (LOGGER.isInfoEnabled()) { LOGGER.info(name + " start to work."); } while (true) { try { SEDAThreadPool.Task inputTask = inputQueue.take(); try { if (hasConflictMap) { if (null != conflictMap.putIfAbsent(inputTask, inputTask)) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(inputTask + " has found in conflictMap, it is abandoned."); } continue; } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug(inputTask + " is put into conflictMap."); } } } SEDAThreadPool.Task outputTask = consume(inputTask); if (hasOutput && null != outputTask) { outputQueue.put(outputTask); if (LOGGER.isDebugEnabled()) { LOGGER.debug(outputTask + " put into outputQueue."); } } } finally { if (hasConflictMap && null != conflictMap.remove(inputTask)) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(inputTask + " is removed from conflictMap."); } } } } catch (Exception e) { LOGGER.error("Error:" + e.getMessage(), e); } } } private SEDAThreadPool.Task consume(SEDAThreadPool.Task task) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(task + " takes from inputQueue."); } return task.execute() ? task : null; } } /** * <pre> * SEDA的Task接口 * @author kanpiaoxue * </pre> * */ public interface Task { public boolean execute(); } }
import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import com.wanmei.parallel.seda.SEDAThreadPool.Task; public class Test { /** * @param args */ public static void main(String[] args) { BlockingQueue<SEDAThreadPool.Task> inputQueue = new LinkedBlockingQueue<SEDAThreadPool.Task>(); BlockingQueue<SEDAThreadPool.Task> inputQueue2 = new LinkedBlockingQueue<SEDAThreadPool.Task>(); BlockingQueue<SEDAThreadPool.Task> inputQueue3 = new LinkedBlockingQueue<SEDAThreadPool.Task>(); ConcurrentHashMap<SEDAThreadPool.Task, SEDAThreadPool.Task> conflictMap = test(); int threadPoolSize = Runtime.getRuntime().availableProcessors() * 4; ExecutorService exec = Executors.newCachedThreadPool(); SEDAThreadPool pool = new SEDAThreadPool("consumer-1-", inputQueue, inputQueue2, exec, threadPoolSize, conflictMap); pool.createSEDAThreadPool(); SEDAThreadPool pool2 = new SEDAThreadPool("consumer-2-", inputQueue2, inputQueue3, exec, threadPoolSize, conflictMap); pool2.createSEDAThreadPool(); SEDAThreadPool pool3 = new SEDAThreadPool("consumer-3-", inputQueue3, exec, threadPoolSize, conflictMap); pool3.createSEDAThreadPool(); exec.execute(new Test().new Producer("producer", inputQueue)); exec.shutdown(); } private static ConcurrentHashMap<SEDAThreadPool.Task, SEDAThreadPool.Task> test() { ConcurrentHashMap<SEDAThreadPool.Task, SEDAThreadPool.Task> conflictMap = new ConcurrentHashMap<SEDAThreadPool.Task, SEDAThreadPool.Task>(); for (int i = 0; i < 10; i++) { Test.TaskImpl t = new Test().new TaskImpl("task-" + i); conflictMap.put(t, t); } return conflictMap; } private class Producer implements Runnable { private final String name; private final BlockingQueue<SEDAThreadPool.Task> outputQueue; public Producer(String name, BlockingQueue<Task> outputQueue) { super(); this.name = name; this.outputQueue = outputQueue; } @Override public void run() { Thread.currentThread().setName(name); while (true) { try { for (SEDAThreadPool.Task t : getTasks()) { outputQueue.put(t); } TimeUnit.SECONDS.sleep(10); } catch (Exception e) { e.printStackTrace(); } } } private List<SEDAThreadPool.Task> getTasks() { List<SEDAThreadPool.Task> list = new ArrayList<SEDAThreadPool.Task>(); for (int i = 0; i < 10; i++) { list.add(new Test().new TaskImpl("task-" + i)); } return list; } } private class TaskImpl implements SEDAThreadPool.Task { private String name; public TaskImpl(String name) { super(); this.name = name; } @Override public int hashCode() { final int prime = 37; int result = 17; result = prime * result + getOuterType().hashCode(); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TaskImpl other = (TaskImpl) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "Task [name=" + name + "]"; } @Override public boolean execute() { try { TimeUnit.SECONDS.sleep(10); } catch (Exception e) { e.printStackTrace(); } return true; } private Test getOuterType() { return Test.this; } } }
参考: http://www.eecs.harvard.edu/~mdw/proj/seda/