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();
    }

相关推荐

  1. <span style='color:red;'>Semaphore</span>

    Semaphore

    2024-04-24 18:38:03      9 阅读
  2. <span style='color:red;'>Semaphore</span>

    Semaphore

    2024-04-24 18:38:03      12 阅读
  3. Semaphore的简单使用

    2024-04-24 18:38:03       32 阅读
  4. 信号量Semaphore

    2024-04-24 18:38:03       13 阅读
  5. C++20 semaphore(信号量) 详解

    2024-04-24 18:38:03       12 阅读
  6. Semaphone应用&源码分析(二)

    2024-04-24 18:38:03       40 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-24 18:38:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-24 18:38:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-24 18:38:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-24 18:38:03       18 阅读

热门阅读

  1. Dubbo

    Dubbo

    2024-04-24 18:38:03      10 阅读
  2. jvm学习笔记

    2024-04-24 18:38:03       9 阅读
  3. 快速制作个人电子签名

    2024-04-24 18:38:03       8 阅读
  4. TypeScript学习笔记7-枚举

    2024-04-24 18:38:03       10 阅读
  5. TCP案例-实时群聊

    2024-04-24 18:38:03       9 阅读
  6. AIGC技术/趋势

    2024-04-24 18:38:03       9 阅读
  7. Git泄露

    Git泄露

    2024-04-24 18:38:03      13 阅读
  8. 面向对象设计模式

    2024-04-24 18:38:03       11 阅读