java多线程编程--Semaphore----信号灯

参考:https://zhuanlan.zhihu.com/p/98593407

Semaphore----信号灯

Semaphore翻译成字面意思为 信号量,Semaphore可以控同时访问的线程个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

2个构造器:

  • public Semaphore(int permits) {
    //参数permits表示许可数目,即同时可以允许多少线程进行访问
    sync = new NonfairSync(permits); }

  • public Semaphore(int permits, boolean fair) {
    //这个多了一个参数fair表示是否是公平的,即等待时间越久的越先获取许可
    sync = (fair)? new FairSync(permits) : new NonfairSync(permits); }

Semaphore类中比较重要的几个方法

,首先是acquire()、release()方法:

  1. public void acquire() throws InterruptedException { } //获取一个许可
  2. public void acquire(int permits) throws InterruptedException { }
    //获取permits个许可
  3. public void release() { } //释放一个许可
  4. public void release(int permits) { } //释放permits个许可

acquire()用来获取一个许可,若无许可能够获得,则会一直等待,直到获得许可。

release()用来释放许可。注意,在释放许可之前,必须先获获得许可。

这4个方法都会被阻塞,如果想立即得到执行结果,可以使用下面几个方法:

  • public boolean tryAcquire() { };
    //尝试获取一个许可,若获取成功,则立即返回true,若获取失败,则立即返回false
  • public boolean tryAcquire(long timeout, TimeUnit unit) throws
    InterruptedException { };
    //尝试获取一个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false
  • public boolean tryAcquire(int permits) { };
    //尝试获取permits个许可,若获取成功,则立即返回true,若获取失败,则立即返回false
  • public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
    throws InterruptedException { };
    //尝试获取permits个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回false

案例:

假若一个工厂有5台机器,但是有8个工人,一台机器同时只能被一个工人使用,只有使用完了,其他工人才能继续使用。那么我们就可以通过Semaphore来实现:

package com.example.dtest.threadTest.use;

import java.util.concurrent.Semaphore;


/*
* 实现一个容器,提供两个方法add、size,写两个线程:

线程1,添加10个元素到容器中
线程2,实时监控元素个数,当个数到5个时,线程2给出提示并结束
* */
public class SemaphoreTest {

    public static void main(String[] args) {
        int N = 8;            //工人数
        Semaphore semaphore = new Semaphore(5); //机器数目
        for(int i=0;i<N;i++)
            new Worker(i,semaphore).start();
    }

    static class Worker extends Thread{
        private int num;
        private Semaphore semaphore;
        public Worker(int num,Semaphore semaphore){
            this.num = num;
            this.semaphore = semaphore;
        }

        @Override
        public void run() {
            try {
                semaphore.acquire();
                System.out.println("工人"+this.num+"占用一个机器在生产...");
                Thread.sleep(2000);
                System.out.println("工人"+this.num+"释放出机器");
                semaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

在这里插入图片描述

Semaphore常用方法说明

  • acquire() 获取一个令牌,在获取到令牌、或者被其他线程调用中断之前线程一直处于阻塞状态。

  • acquire(int permits) 获取一个令牌,在获取到令牌、或者被其他线程调用中断、或超时之前线程一直处于阻塞状态。

  • acquireUninterruptibly() 获取一个令牌,在获取到令牌之前线程一直处于阻塞状态(忽略中断)。

  • tryAcquire() 尝试获得令牌,返回获取令牌成功或失败,不阻塞线程。

  • tryAcquire(long timeout, TimeUnit unit)
    尝试获得令牌,在超时时间内循环尝试获取,直到尝试获取成功或超时返回,不阻塞线程。

  • release() 释放一个令牌,唤醒一个获取令牌不成功的阻塞线程。

  • hasQueuedThreads() 等待队列里是否还存在等待线程。

  • getQueueLength() 获取等待队列里阻塞的线程数。

  • drainPermits() 清空令牌把可用令牌数置为0,返回清空令牌的数量。

  • availablePermits() 返回可用的令牌数量。

用semaphore 实现停车场提示牌功能。

每个停车场入口都有一个提示牌,上面显示着停车场的剩余车位还有多少,当剩余车位为0时,不允许车辆进入停车场,直到停车场里面有车离开停车场,这时提示牌上会显示新的剩余车位数。

业务场景 :

1、停车场容纳总停车量10。

2、当一辆车进入停车场后,显示牌的剩余车位数响应的减1.

3、每有一辆车驶出停车场后,显示牌的剩余车位数响应的加1。

4、停车场剩余车位不足时,车辆只能在外面等待。

package com.example.dtest.threadTest.use;

import java.util.Random;
import java.util.concurrent.Semaphore;

public class SemaphoreTest02 {

//    停车场同时容纳的车辆10
    private static Semaphore semaphore = new Semaphore(10);

    public static void main(String[] args) {

//        模拟100辆车进入停车场
        for(int i=0; i<100 ;i++){

         Thread thread = new Thread(new Runnable() {
             @Override
             public void run() {

                 System.out.println("===="+Thread.currentThread().getName()+"来到停车场");
                 if(semaphore.availablePermits() == 0){
                     System.out.println("车位不足,耐心等待");
                 }
                 try {
                     semaphore.acquire();//获取令牌尝试进入停车场
                     System.out.println(Thread.currentThread().getName()+"成功进入停车场");
                     Thread.sleep(new Random().nextInt(10000));//模拟车辆在停车场停留的时间
                     System.out.println(Thread.currentThread().getName()+"驶出停车场");
                     semaphore.release();//释放令牌,腾出停车场车位
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }

             }
         },i+"号车");

         thread.start();

        }

    }

}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一个简单的Java多线程模拟交通信号灯的示例代码。 ``` public class TrafficSignal implements Runnable { private String name; private int greenTime; // 绿灯时间 private int yellowTime; // 黄灯时间 private int redTime; // 红灯时间 public TrafficSignal(String name, int greenTime, int yellowTime, int redTime) { this.name = name; this.greenTime = greenTime; this.yellowTime = yellowTime; this.redTime = redTime; } @Override public void run() { while (true) { System.out.println(name + " 绿灯亮起"); try { Thread.sleep(greenTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + " 黄灯亮起"); try { Thread.sleep(yellowTime); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + " 红灯亮起"); try { Thread.sleep(redTime); } catch (InterruptedException e) { e.printStackTrace(); } } } } ``` 在这个示例中,我们定义了一个TrafficSignal类,它实现了Runnable接口。这个类有四个属性:name表示交通信号灯的名称,greenTime表示绿灯时间,yellowTime表示黄灯时间,redTime表示红灯时间。 在run()方法中,我们使用while循环模拟交通信号灯的不停循环。在循环中,我们依次输出绿灯、黄灯、红灯,并使用Thread.sleep()方法模拟灯亮起时间。 接下来,我们可以创建多个TrafficSignal对象,然后启动多个线程,来模拟多个交通信号灯。示例代码如下: ``` public class TestTrafficSignal { public static void main(String[] args) { TrafficSignal signal1 = new TrafficSignal("南北路口", 5000, 2000, 5000); TrafficSignal signal2 = new TrafficSignal("东西路口", 3000, 1000, 3000); Thread thread1 = new Thread(signal1); Thread thread2 = new Thread(signal2); thread1.start(); thread2.start(); } } ``` 在这个示例中,我们创建了两个TrafficSignal对象:南北路口和东西路口。然后,我们创建了两个Thread对象,并把TrafficSignal对象作为参数传递给它们。最后,我们启动了这两个线程,模拟了两个交通信号灯的运行。 希望这个简单的示例代码能够帮助您了解Java多线程模拟交通信号灯的实现方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值