import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * Created by Administrator on 2017/10/11. */ class Count { private int count = 0; private Random rand = new Random(47); //remove the synchronized keyword to see counting faild public synchronized int increment() { int temp = count; System.out.print("count: " + count); //nextBoolean用於從該隨機數生成器的序列獲得下一個僞均勻分佈的布爾值。 //yield half the time if (rand.nextBoolean()) Thread.yield(); return (count = ++temp); } public synchronized int value() { return count; } } class Entrance implements Runnable { private static Count count = new Count(); private static List<Entrance> entrances = new ArrayList<Entrance>(); private int number = 0; //doesn't need synchronization to read private int id; private static volatile boolean canceled = false; //atomic operation on a volatile field: public static void cancel() { canceled = true; } public Entrance(int id) { this.id = id; //keep this task in a list. Also prevents //garbage collection of dead tasks entrances.add(this); } public void run() { while (!canceled) { synchronized (this) { ++number; } System.out.println(this + " Total: " + count.increment()); try { TimeUnit.MICROSECONDS.sleep(100); } catch (InterruptedException e) { System.out.print("sleep interrupted"); } } System.out.print("Stopping " + this + "\n"); } public synchronized int getValue() { return number; } public String toString() { return "Entrance " + id + ": " + getValue() + " "; } public static int getTotalCount() { return count.value(); } public static int sumEntrances() { int sum = 0; for (Entrance entrance : entrances) { sum += entrance.getValue(); } return sum; } } public class OrnamentalGarden { public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { exec.execute(new Entrance(i)); } //Run for a while ,then stop and collect the data: TimeUnit.SECONDS.sleep(1); Entrance.cancel(); exec.shutdown(); if (!exec.awaitTermination(250, TimeUnit.MICROSECONDS)) System.out.print("Some tasks were not terminated!"); System.out.print("\nTotal: " + Entrance.getTotalCount()); System.out.print("\nSum of Entrances: " + Entrance.sumEntrances()); } }
count: 0Entrance 2: 1 Total: 1
count: 1Entrance 4: 1 Total: 2
count: 2Entrance 3: 1 Total: 3
count: 3Entrance 1: 1 Total: 4
count: 4Entrance 0: 1 Total: 5
count: 5Entrance 2: 2 Total: 6
count: 6Entrance 3: 2 Total: 7
count: 7Entrance 0: 2 Total: 8
count: 8Entrance 1: 2 Total: 9
count: 9Entrance 4: 2 Total: 10
count: 10Entrance 1: 3 Total: 11
count: 11Entrance 0: 3 Total: 12
count: 12Entrance 4: 3 Total: 13
count: 13Entrance 2: 3 Total: 14
count: 14Entrance 3: 3 Total: 15
count: 15Entrance 1: 4 Total: 16
count: 16Entrance 3: 4 Total: 17
count: 17Entrance 2: 4 Total: 18
count: 18Entrance 4: 4 Total: 19
count: 19Entrance 0: 4 Total: 20
count: 20count: 21Entrance 3: 5 Total: 22
Entrance 2: 5 Total: 21
count: 22Entrance 4: 5 Total: 23
count: 23Entrance 0: 5 Total: 24
count: 24Entrance 1: 5 Total: 25
count: 25Entrance 3: 6 Total: 26
count: 26Entrance 0: 6 Total: 27
count: 27Entrance 4: 6 Total: 28
count: 28Entrance 2: 6 Total: 29
count: 29Entrance 1: 6 Total: 30
count: 30Entrance 3: 7 Total: 31
count: 31Entrance 4: 7 Total: 32
count: 32Entrance 2: 7 Total: 33
count: 33Entrance 1: 7 Total: 34
count: 34Entrance 0: 7 Total: 35
count: 35Entrance 2: 8 Total: 36
count: 36Entrance 4: 8 Total: 37
count: 37Entrance 0: 8 Total: 38
count: 38Entrance 1: 8 Total: 39
count: 39Entrance 3: 8 Total: 40
count: 40Entrance 3: 9 Total: 41
count: 41Entrance 4: 9 Total: 42
count: 42Entrance 0: 9 Total: 43
count: 43Entrance 1: 9 Total: 44
count: 44Entrance 2: 9 Total: 45
count: 45Entrance 4: 10 Total: 46
count: 46Entrance 3: 10 Total: 47
count: 47Entrance 1: 10 Total: 48
count: 48Entrance 0: 10 Total: 49
count: 49Entrance 2: 10 Total: 50
count: 50count: 51Entrance 2: 11 Total: 51
Entrance 4: 11 Total: 52
count: 52Entrance 1: 11 Total: 53
count: 53Entrance 0: 11 Total: 54
count: 54Entrance 3: 11 Total: 55
count: 55Entrance 3: 12 Total: 56
count: 56Entrance 4: 12 Total: 57
count: 57Entrance 2: 12 Total: 58
count: 58Entrance 1: 12 Total: 59
count: 59Entrance 0: 12 Total: 60
count: 60Entrance 4: 13 Total: 61
count: 61Entrance 0: 13 Total: 62
count: 62Entrance 1: 13 Total: 63
count: 63Entrance 2: 13 Total: 64
count: 64Entrance 3: 13 Total: 65
count: 65Entrance 1: 14 Total: 66
count: 66Entrance 2: 14 Total: 67
count: 67Entrance 4: 14 Total: 68
count: 68Entrance 3: 14 Total: 69
count: 69Entrance 0: 14 Total: 70
count: 70Entrance 1: 15 Total: 71
count: 71Entrance 0: 15 Total: 72
count: 72Entrance 3: 15 Total: 73
count: 73Entrance 2: 15 Total: 74java
。。。。。。dom
count: 4817Entrance 0: 962 Total: 4818
Entrance 4: 966 Total: 4815
count: 4818Entrance 1: 967 Total: 4819
Stopping Entrance 2: 958
Stopping Entrance 1: 967
Stopping Entrance 0: 962
Stopping Entrance 4: 966
Stopping Entrance 3: 966 this
Total: 4819
Sum of Entrances: 4819
Process finished with exit code 0atom
場景:一個花園,N個門,統計天天經過每一個門口進入的參觀者。設計
設計:經過使用單個的Count對象來跟蹤花園參觀者的主計數值,而且將其看成Entrance類中的一個靜態域進行存儲。code
Count.increment()和Count.value()都是synchronized的,用來控制對count域的訪問。increment()方法使用了Random對象,目的是在從把count讀取到temp中,到遞增temp並將其存儲回count的這段時間裏,有大約一半的時間產生讓步。若是你將increment()上的synchronized關鍵字註釋掉,那麼這個程序就會崩潰,由於多個任務將同時訪問並修改count(yield()會使問題更快地發生)對象
number是Entrance任務裏維護的,它包含經過某個特定入口進行的參觀者的數量。這提供了對count對象的雙重檢查,以確保其記錄的參觀者數量是正確的。Entrance.run()只是遞增number和count對象,而後休眠100ms.rem