下课回来,突然发现之前发的一篇日志没了,奇怪。为了记录那天的学习内容,还是再写一遍好了。
------------------------------------------
有如下场景,一个停车场,有3个车位,现有10个顾客,每个人均要把车停在这里一段时间。显然,当3个车位都被占用时,其他的人要等候,知道有人离开,空出车位。
写个小程序模拟这一场景。
这个场景还是很简单的,而且很明显可以用信号量来实现。
-二元信号量相当于锁的作用
-初始成0的信号量可以用来阻塞一个线程
-与锁机制不同,进行V和P操作的线程不一定是同一个。而上锁和解锁的线程,当然这里指对同一个对象,一定是同一个。
第一步,写一个简单的semaphore类
- package semaphore;
- public class Semaphore {
- private int count;
- private Object mutex;//这个锁是必须要用的,因为这里有个count变量会被很多线程共享使用
-
- //这两个string是做测试用的
- private final String message_1 = " I get a place !!";
- private final String message_2 = " I 've leaved !!";
- public Semaphore(int n) {
- this.count = n;
- this.mutex = new Object();
- }
- public void P_operation(String name) throws InterruptedException {
- synchronized (mutex) {
- while (count == 0) {
- System.out.println(name + " is waiting");
- mutex.wait();
- }
- count--;
- System.out.println(name+message_1);
- }
- }
- public void V_operation(String name) {
- synchronized (mutex) {
- count++;
- System.out.println(name+message_2);
- mutex.notify();
- }
- }
- }
实现模拟这一过程的线程类
- package semaphore;
- public class Park extends Thread {
- private Semaphore sph;
- private String name;
- public Park(Semaphore s, String name) {
- super(name);
- this.name = name;
- this.sph = s;
- }
- public void parking() {
- try {
- Thread.sleep((long) (Math.random() * 1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- public void run() {
- try {
- sph.P_operation(name);
- } catch (InterruptedException e1) {
- e1.printStackTrace();
- }
- parking();//随机停留时间
- sph.V_operation(name);
- }
- }
测试类
- package semaphore;
- public class Main {
- public static void main(String[] args) {
-
- Semaphore sph = new Semaphore(3);
-
- Thread []park = new Thread[10];
-
- for(int i = 0;i<10;i++){
- park[i] = new Park(sph,"client-"+i);
- park[i].start();
- }
-
- }
- }
输出结果如下
- client-0 I get a place !!
- client-1 I get a place !!
- client-2 I get a place !!
- client-3 is waiting
- client-4 is waiting
- client-5 is waiting
- client-6 is waiting
- client-7 is waiting
- client-8 is waiting
- client-9 is waiting
- client-2 I 've leaved !!
- client-3 I get a place !!
- client-1 I 've leaved !!
- client-4 I get a place !!
- client-0 I 've leaved !!
- client-5 I get a place !!
- client-4 I 've leaved !!
- client-6 I get a place !!
- client-3 I 've leaved !!
- client-7 I get a place !!
- client-6 I 've leaved !!
- client-8 I get a place !!
- client-8 I 've leaved !!
- client-9 I get a place !!
- client-5 I 've leaved !!
- client-9 I 've leaved !!
- client-7 I 've leaved !!
-如果改动下这个场景
假如顾客中分为普通顾客和vip顾客,这时,需要让vip优先得到车位。
这时,我们就需要2个等待队列,一个是用来等待空闲车位的,另一个则是等待vip的队列,显然,这个队列中只有普通顾客线程。
当一个普通顾客线程被从等待空闲成为的队列中唤醒时,它可能马上又进入了第二个等待队列。
此时,使用条件变量更加方便。因为每个条件变量,都有一个队列与其对应。思路也更加清晰。
阅读(855) | 评论(0) | 转发(0) |