Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43402
  • 博文数量: 10
  • 博客积分: 253
  • 博客等级: 二等列兵
  • 技术积分: 131
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-09 08:08
文章分类
文章存档

2012年(10)

我的朋友

分类: Java

2012-04-16 18:54:14


下课回来,突然发现之前发的一篇日志没了,奇怪。为了记录那天的学习内容,还是再写一遍好了。
 
------------------------------------------
有如下场景,一个停车场,有3个车位,现有10个顾客,每个人均要把车停在这里一段时间。显然,当3个车位都被占用时,其他的人要等候,知道有人离开,空出车位。
写个小程序模拟这一场景。
 
这个场景还是很简单的,而且很明显可以用信号量来实现。
 
-二元信号量相当于锁的作用
-初始成0的信号量可以用来阻塞一个线程
-与锁机制不同,进行V和P操作的线程不一定是同一个。而上锁和解锁的线程,当然这里指对同一个对象,一定是同一个。
 
第一步,写一个简单的semaphore类
 

点击(此处)折叠或打开

  1. package semaphore;

  2. public class Semaphore {

  3.     private int count;
  4.     private Object mutex;//这个锁是必须要用的,因为这里有个count变量会被很多线程共享使用

  5.     
  6.     //这两个string是做测试用的

  7.     private final String message_1 = " I get a place !!";
  8.     private final String message_2 = " I 've leaved !!";

  9.     public Semaphore(int n) {

  10.         this.count = n;
  11.         this.mutex = new Object();

  12.     }

  13.     public void P_operation(String name) throws InterruptedException {

  14.         synchronized (mutex) {

  15.             while (count == 0) {
  16.                 System.out.println(name + " is waiting");
  17.                 mutex.wait();
  18.             }

  19.             count--;
  20.             System.out.println(name+message_1);

  21.         }

  22.     }

  23.     public void V_operation(String name) {

  24.         synchronized (mutex) {
  25.             count++;
  26.             System.out.println(name+message_2);
  27.             mutex.notify();
  28.         }

  29.     }

  30. }

实现模拟这一过程的线程类

点击(此处)折叠或打开

  1. package semaphore;

  2. public class Park extends Thread {

  3.     private Semaphore sph;
  4.     private String name;

  5.     public Park(Semaphore s, String name) {

  6.         super(name);
  7.         this.name = name;
  8.         this.sph = s;

  9.     }

  10.     public void parking() {

  11.         try {
  12.             Thread.sleep((long) (Math.random() * 1000));
  13.         } catch (InterruptedException e) {
  14.             e.printStackTrace();
  15.         }

  16.     }

  17.     public void run() {
  18.         try {
  19.             sph.P_operation(name);
  20.         } catch (InterruptedException e1) {
  21.             e1.printStackTrace();
  22.         }

  23.         parking();//随机停留时间

  24.         sph.V_operation(name);
  25.     }

  26. }
测试类

点击(此处)折叠或打开

  1. package semaphore;

  2. public class Main {
  3.     public static void main(String[] args) {
  4.         
  5.         Semaphore sph = new Semaphore(3);
  6.         
  7.         Thread []park = new Thread[10];
  8.         
  9.         for(int i = 0;i<10;i++){        
  10.             park[i] = new Park(sph,"client-"+i);
  11.             park[i].start();
  12.         }
  13.         
  14.     }
  15. }

输出结果如下

点击(此处)折叠或打开

  1. client-0 I get a place !!
  2. client-1 I get a place !!
  3. client-2 I get a place !!
  4. client-3 is waiting
  5. client-4 is waiting
  6. client-5 is waiting
  7. client-6 is waiting
  8. client-7 is waiting
  9. client-8 is waiting
  10. client-9 is waiting
  11. client-2 I 've leaved !!
  12. client-3 I get a place !!
  13. client-1 I 've leaved !!
  14. client-4 I get a place !!
  15. client-0 I 've leaved !!
  16. client-5 I get a place !!
  17. client-4 I 've leaved !!
  18. client-6 I get a place !!
  19. client-3 I 've leaved !!
  20. client-7 I get a place !!
  21. client-6 I 've leaved !!
  22. client-8 I get a place !!
  23. client-8 I 've leaved !!
  24. client-9 I get a place !!
  25. client-5 I 've leaved !!
  26. client-9 I 've leaved !!
  27. client-7 I 've leaved !!

 

-如果改动下这个场景

假如顾客中分为普通顾客和vip顾客,这时,需要让vip优先得到车位。

这时,我们就需要2个等待队列,一个是用来等待空闲车位的,另一个则是等待vip的队列,显然,这个队列中只有普通顾客线程。

当一个普通顾客线程被从等待空闲成为的队列中唤醒时,它可能马上又进入了第二个等待队列。

此时,使用条件变量更加方便。因为每个条件变量,都有一个队列与其对应。思路也更加清晰。

 

 



阅读(833) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~