A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© hello_csu 中级黑马   /  2014-12-1 22:18  /  3766 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 hello_csu 于 2014-12-2 12:10 编辑

问题描述:
在看书中遇到如下一个仿真例子:小区委员会苏,希望了解每天通过各个大门进入公园的总人数,每个大门都安装了一个计数器,当人通过事后计数器就会递增,其递增,也表示说总人数的共享计数器也会递增。
需求:现在需要统计出来每个门进入的人数和总人数。
其设计思路:
采用多线程机制,对每个门通过的人数采用一个线程去实现,且通过让其之间共享一个Count计数器去统计总人数。
代码设计如下
  1. /**
  2. *
  3. */
  4. /**
  5. * @author bobwang
  6. *
  7. */
  8. package OrnamentalGarden;

  9. import java.util.concurrent.*;
  10. import java.util.*;
  11. import java.lang.*;

  12. /**
  13. * Descriptsion:Class Count for counting the total pepole.
  14. */
  15. class Count
  16. {

  17.   private int count =0 ;
  18.   private Random rand = new Random(47);
  19.   
  20.   public synchronized int increment() {
  21.         int temp = count;
  22.         if(rand.nextBoolean())
  23.                 Thread.yield();
  24.         return (count= ++temp);
  25.   }

  26.   
  27.   public synchronized int getvalue() {
  28.           return count;
  29.   }
  30. }
  31.   

  32. /**
  33. * Decription:Class Entrance for counting the people that enters this entrance.
  34. */
  35. class Entrance implements Runnable {
  36.         
  37.         //attribute area
  38.         private static Count count = new Count();
  39.         private static  List<Entrance> entrances = new ArrayList<Entrance>();
  40.         private int number = 0;
  41.         private int id;
  42.         private static volatile boolean canceled = false;
  43.         
  44.         //static method area
  45.         
  46.         public static void cancel() {
  47.                 canceled = true;
  48.         }
  49.         
  50.         public static int getTotalCount() {
  51.                 return count.getvalue();
  52.         }
  53.         
  54.         public static int sumEntrances() {
  55.                 int sum =0;
  56.                 for(Entrance e : entrances){
  57.                         sum +=e.getValue();
  58.                 }
  59.                 return sum;
  60.         }
  61.         
  62.         //Contructor area
  63.         public Entrance (int id) {
  64.                 this.id = id;
  65.                 entrances.add(this);
  66.         }

  67.         //Method area
  68.     public synchronized int getValue(){
  69.             return number;
  70.     }
  71.    
  72.     public String toString(){
  73.             return "Entrance"+ id+":"+getValue();
  74.     }
  75.    
  76.     //Override from interface Runnable
  77.         public void run() {
  78.                 while(!canceled)
  79.                 {
  80.                   synchronized(this)
  81.                   {
  82.                           number++;
  83.                   }
  84.                   System.out.println(this+"Total:"+count.increment());
  85.                   try {
  86.                           TimeUnit.MICROSECONDS.sleep(100);
  87.                   }
  88.                   catch(InterruptedException e) {
  89.                           System.out.println("sleep Interrupted");         
  90.                   }
  91.                 }
  92.                
  93.                 System.out.println("Stopping"+this);
  94.         }
  95. }

  96. public class OrnamentalGarden {
  97.         
  98.   public static void main(String[] args) throws Exception {
  99.           ExecutorService exec = Executors.newCachedThreadPool();
  100.           for(int i=0;i<5;i++)
  101.           {
  102.                  exec.execute(new Entrance(i));
  103.           }
  104.           TimeUnit.MILLISECONDS.sleep(20);
  105.           Entrance.cancel();
  106.           exec.shutdown();
  107.          
  108.           if(!exec.awaitTermination(250, TimeUnit.MILLISECONDS))
  109.           {
  110.                 System.out.println("Some task was not closed.");
  111.           }
  112.          
  113.           System.out.println("Total:"+Entrance.getTotalCount());
  114.           System.out.println("Total:"+Entrance.sumEntrances());
  115.   
  116.    }
  117.   
  118. }
复制代码
Output Result:
Entrance0:1Total:1
Entrance1:1Total:2
Entrance2:1Total:3
Entrance3:1Total:4
......
Entrance4:3Total:17
Entrance2:4Total:18
Entrance2:5Total:19
Entrance1:5Total:20
Entrance4:4Total:23
Entrance3:4Total:21
Entrance0:5Total:22
Entrance4:5Total:24
Entrance2:6Total:27
Entrance1:21Total:100
Entrance0:21Total:101
Entrance4:20Total:102
Entrance3:20Total:99
StoppingEntrance2:20
StoppingEntrance1:21
StoppingEntrance3:20
StoppingEntrance4:20
StoppingEntrance0:21
Total:102
Total:102
疑问点:现在Entrance4:4Total:23中是实现监控说每个门都通过的人数和这个时间点总人数,但依照我的理解Total的数目应该是一个递增的趋势值,但是从log输出来看,运行过程中是个比较随机的值,为什么会出现忽大忽小?
谁能帮解答一些,特别感谢。




评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1

查看全部评分

2 个回复

倒序浏览
朋友你代码写的真好,发现你发的帖子都不错,有营养。
线程同步有问题,你是保证了计数器同步,但是没有保证5个线程先后同步问题,你是用了5个不同的锁。
稍微改了一下你的代码。
  1. package myfirst;


  2. import java.util.concurrent.*;
  3. import java.util.*;
  4. import java.lang.*;

  5. /**
  6. * Descriptsion:Class Count for counting the total pepole.
  7. */
  8. class Count
  9. {

  10.   private int count =0 ;
  11.   private Random rand = new Random(47);
  12.   
  13.   public synchronized int increment() {
  14.         int temp = count;
  15.         if(rand.nextBoolean())
  16.                 Thread.yield();
  17.         return (count= ++temp);
  18.   }

  19.   
  20.   public synchronized int getvalue() {
  21.           return count;
  22.   }
  23. }
  24.   

  25. /**
  26. * Decription:Class Entrance for counting the people that enters this entrance.
  27. */
  28. class Entrance implements Runnable {
  29.         
  30.         //attribute area
  31.         private static Count count = new Count();
  32.         private static  List<Entrance> entrances = new ArrayList<Entrance>();
  33.         private int number = 0;
  34.         private int id;
  35.         private static volatile boolean canceled = false;
  36.         
  37.         //static method area
  38.         
  39.         public static void cancel() {
  40.                 canceled = true;
  41.         }
  42.         
  43.         public static int getTotalCount() {
  44.                 return count.getvalue();
  45.         }
  46.         
  47.         public static int sumEntrances() {
  48.                 int sum =0;
  49.                 for(Entrance e : entrances){
  50.                         sum +=e.getValue();
  51.                 }
  52.                 return sum;
  53.         }
  54.         
  55.         //Contructor area
  56.         public Entrance (int id) {
  57.                 this.id = id;
  58.                 entrances.add(this);
  59.         }

  60.         //Method area
  61.     public int getValue(){
  62.             synchronized(this.getClass()) {
  63.             return number;
  64.             }
  65.     }
  66.    
  67.     public String toString(){
  68.             return "Entrance"+ id+":"+getValue();
  69.     }
  70.    
  71.     //Override from interface Runnable
  72.         public void run() {
  73.                 while(!canceled)
  74.                 {
  75.                   synchronized(this.getClass())
  76.                   {
  77.                           number++;
  78.                           System.out.println(this+"Total:"+count.increment());   
  79.                   }
  80.                   
  81.                   try {
  82.                           TimeUnit.MICROSECONDS.sleep(100);
  83.                   }
  84.                   catch(InterruptedException e) {
  85.                           System.out.println("sleep Interrupted");         
  86.                   }
  87.                 }
  88.                
  89.                 System.out.println("Stopping"+this);
  90.         }
  91. }

  92. public class OrnametalGarden {
  93.         
  94.   public static void main(String[] args) throws Exception {
  95.           ExecutorService exec = Executors.newCachedThreadPool();
  96.           for(int i=0;i<5;i++)
  97.           {
  98.                  exec.execute(new Entrance(i));
  99.           }
  100.           TimeUnit.MILLISECONDS.sleep(20);
  101.           Entrance.cancel();
  102.           exec.shutdown();
  103.          
  104.           if(!exec.awaitTermination(250, TimeUnit.MILLISECONDS))
  105.           {
  106.                 System.out.println("Some task was not closed.");
  107.           }
  108.          
  109.           System.out.println("Total:"+Entrance.getTotalCount());
  110.           System.out.println("Total:"+Entrance.sumEntrances());
  111.   
  112.    }
  113.   
  114. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1

查看全部评分

回复 使用道具 举报 1 0
感谢kernel楼主,你这样子一解释,我豁然明白了,非常谢谢!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马