Semaphore

什么是Semaphore:

信号量

在前面的学习中,我们使用了synchronized加锁,后面reentrantLock加锁从而实现多线程并发运行,但这两个的特点都是:在一段时间内只允许一个线程处于允许状态,其他线程都处于阻塞状态

那么咱们的Semaphore就可以在某个时间指定数量个线程运行


主要方法:

1.构造方法:指定初始资源的数量 (int permits)  是否为公平锁(boolean fair)

public Semaphore(int permits) {
        sync = new NonfairSync(permits);
    }

public Semaphore(int permits, boolean fair){
        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
    }

2.acquire():获取资源 如果是无参 ,默认获取一个资源  

public void acquire(int permits) throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

3.release():释放资源  无参,默认释放一个资源  

 public void acquire(int permits) throws InterruptedException {
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireSharedInterruptibly(permits);
    }

acquire:
 public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(4);
        System.out.println("取了一个资源");
        semaphore.acquire(); //默认取一个资源
        System.out.println("取了三个资源 资源被取完");
        semaphore.acquire(3);
        
        //此时资源量已经为0了 如果继续取资源就会阻塞
        semaphore.acquire();
        System.out.println("被阻塞 执行不到下面代码");
    }

创建Semaphore对象时初始化资源类值,当acquire完所有资源后,再acquire此时就会阻塞


release():
 public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(4);
        System.out.println("取了一个资源");
        semaphore.acquire(); //默认取一个资源
        System.out.println("取了三个资源 资源被取完");
        semaphore.acquire(3);

        //释放一个资源 此后又可以取了
        System.out.println("释放一个资源");
        semaphore.release();

        //取资源
        semaphore.acquire();
        System.out.println("取一个资源");
    }

此方法为释放资源,使资源量+1,实例化Semaphore对象时给出的资源量初始值并不是最大资源数,release可以往上继续增加资源量

 public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(4);
        semaphore.release(1);
        semaphore.acquire(4);
        semaphore.acquire();
        System.out.println("获取了5个资源量");
    }


模拟停车场系统:
 public static void main(String[] args) {
        //通过Semaphore实现停车场停车位实例
        //规定停车场有5个停车位
        Semaphore semaphore = new Semaphore(5);
        //lambda表达式对原子类不会变量捕获
        AtomicInteger comeCar = new AtomicInteger();
        Thread come = new Thread(() -> {
            while (true) {
                try {
                    //随机5-10秒内 就会进来一辆车
                    Thread.sleep(new Random().nextInt(1000) + 1000);
                    semaphore.acquire();
                    comeCar.getAndIncrement();
                    System.out.println("come:" + comeCar + "辆车进来了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        AtomicInteger outCar = new AtomicInteger();
        Thread out = new Thread(() -> {
            while (true) {
                //随机10-20秒内 就会出去一辆车
                try {
                    Thread.sleep(new Random().nextInt(1000) + 2000);
                    //释放资源
                    semaphore.release();
                    outCar.getAndIncrement();
                    System.out.println("out:有" + outCar + "辆车出去了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        come.start();
        out.start();
    }

当车停满后,车辆就进不来了,除非有车出停车场,Semaphore很匹配这个场景


两个线程交替打印
 public static void main(String[] args) {
        //使用两个信号量控制两个线程交替打印
        //如果只使用一个信号量是不好控制的 由于线程调度的随机性 或多或少都会出现几次极端情况
        Semaphore s1 = new Semaphore(1);
        Semaphore s2 = new Semaphore(0);

        Thread t1 = new Thread(() -> {
            for(int i = 0 ;i < 5; i++){
                try {
                    s1.acquire();
                    System.out.println("my name is KiKi");
                    s2.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(() -> {
            for(int i = 0 ;i < 5; i++){
                try {
                    s2.acquire();
                    System.out.println("my name is LaLa");
                    s1.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t1.start();
        t2.start();
    }

使用两个信号量,一个控制t1线程,一个控制t2线程,当t1线程完成打印后,释放线程2的信号量,使t2线程可以打印,t2线程完成打印后,再释放线程1的信号量


三个线程交替打印
public static void main(String[] args) throws InterruptedException {
        Semaphore s1 = new Semaphore(1);
        Semaphore s2 = new Semaphore(0);
        Semaphore s3 = new Semaphore(0);

        Thread t1= new Thread(() -> {
            for(int i = 0; i < 3; i++){
                try {
                    s1.acquire();
                    System.out.print("A ");
                    s2.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });

        Thread t2 = new Thread(() -> {
            for(int i = 0; i < 3; i++){
                try {
                    s2.acquire();
                    System.out.print("B ");
                    s3.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });

        Thread t3 = new Thread(() -> {
            for(int i = 0; i < 3; i++){
                try {
                    s3.acquire();
                    System.out.print("C ");
                    s1.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
        t1.start();
        t2.start();
        t3.start();
    }

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值