题目:有一所很大的花园,花园提供了多个大门供游人进出花园,花园供应商希望了解每天通过多个大门进入公园的总人数。每个大门都有一个计数器,并且任何一个计数器递增的时候,就表示公园当中的总人数也会递增,反之同理。每一个游客可能从一个大门进入以后从另外的一个大门出去。
分析:这是一个典型的多线程共享资源冲突的算法,有一个总人数,为共享资源,而那几个大门就是不同的任务,随时随地的对人数这个资源进行着读写,所以同步操作一定要注意。下面通过一个Demo来模拟上述场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
public class OrnamentalGrden { public static void main(String[] args) throws InterruptedException { ExecutorService threadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { threadPool.execute(new Door(i)); } TimeUnit.SECONDS.sleep(3); Door.cancel(); threadPool.shutdown(); if (!threadPool.awaitTermination(250, TimeUnit.MILLISECONDS)) { System.out.println("some tasks were not terminated!"); } System.out.println("Total : " + Door.getTotalCount()); System.out.println("sum of door: " + Door.sumCount()); } }
class Door implements Runnable { private static Count sCount = new Count() ; private static List<Door> sDoorList = new ArrayList<Door>(); private static volatile boolean sCanceled = false ; private int number = 0; private final int ID ; public Door (int id) { this.ID = id ; sDoorList.add(this) ; } @Override public void run() { while (!sCanceled) { synchronized (this) { ++ number; } System.out.println(this + "Totle : " + sCount.increment()); try{ TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { System.out.println("sleep interrupted"); } } System.out.println("stopping " + this); } public synchronized int getValue () { return number ; } public static void cancel() { sCanceled = true ; } @Override public String toString() { return "Door " + ID + " : " + getValue(); } public static int getTotalCount () { return sCount.value() ; } public static int sumCount () { int sum = 0 ; for (Door door : sDoorList) { sum += door.getValue() ; } return sum ; } }
class Count { private int count = 0 ; private Random random = new Random(47); public synchronized int increment () { int temp = count ; if (random.nextBoolean()) { Thread.yield(); } return (count = ++temp); } public synchronized int value () {return count ;} }
|