package com.github.rfqu.reduceMaps; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; /** * http://stackoverflow.com/questions/23179438/multithreaded-merge-best-java-threading-practices-recommended * * @author rfq * */ public class ReduceMaps { AtomicInteger threadNums = new AtomicInteger(); MapQueue mapQueue = new MapQueue(); static class MapQueue { LinkedList<Map> queue = new LinkedList<Map>(); int threadcount = 0; boolean genStopped = false; //将Map加入队列中. 队列采用LinkedList实现 public synchronized void put(Map map) { queue.add(map); //队列中有数据,通知其他线程取数据 notifyAll(); } //停止生成数据,但是队列中不一定就没有数据了.只是说从此开始,队列不会有新数据生成了 public synchronized void stop() { genStopped = true; notifyAll(); } public synchronized Map takeFirst() { for (;;) { //取队列的第一个元素. LinkedList链表. 最开始加入的元素在表头. //所以最先加入的,会被最先取出来, 实现了队列的FIFO功能 Map res = queue.poll(); if (res != null) { threadcount++; return res; } if (genStopped) { System.out.println("takeFirst failed"); return null; } //如果队列中没有数据且生成器没有停止生成数据,则等待.直到队列中有数据时,会触发通知,这里不再等待 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized Map takeNext(Map myMap) { for (;;) { // Map res=queue.poll(); if (res != null) { return res; } if (genStopped) { threadcount--; if (threadcount == 0) { // all done - push the resulting map further System.out.println("all done"); } else { put(myMap); } notifyAll(); return null; } try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class MapGenerator implements Runnable { @Override public void run() { for (int k = 0; k < 10; k++) { HashMap map = new HashMap(); map.put("n", k); System.out.println("put "+k); //模拟产生Map数据,并把多个Map加入到List中. mapQueue中一旦有Map产生,就会通知其他线程取数据 mapQueue.put(map); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } //停止生成数据 mapQueue.stop(); } } class MapReducer implements Runnable { Map myMap; int threadNum=threadNums.incrementAndGet(); void print(String msg, Map... maps) { StringBuilder sb = new StringBuilder(); sb.append("thr: ").append(threadNum).append(" :").append(msg); for (Map map: maps) { sb.append(" #"); if (map==null) { sb.append("null"); } else { Integer n = ((Integer) map.get("n")); sb.append(n); } } System.out.println(sb.toString()); } @Override public void run() { //取队列的第一个元素 myMap=mapQueue.takeFirst(); if (myMap==null) { print("takeFirst failed"); return; } print("takeFirst success", myMap); for (;;) { Map other=mapQueue.takeNext(myMap); if (other==null) { print("exiting", myMap); return; } print("takeNext success", other); merge(other); } } void merge(Map other) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } print("merged", myMap, other); } } void test() { new Thread(new MapGenerator()).start(); for (int k = 0; k < 3; k++) { new Thread(new MapReducer()).start(); } } public static void main(String[] args) { new ReduceMaps().test(); } }