Java并发编程之工具类Semaphore的使用

接下来我将详细讲解Java并发编程中Semaphore工具类的使用。

Semaphore介绍

Semaphore是一种计数信号量,它可以用来控制同时访问某个特定资源的线程数量。 对于使用Semaphore的程序来说,如果控制的资源达到上限,请求资源的线程就会被阻塞。

Semaphore可以看做是一种更高级别的锁,它能够限制同时访问共享资源的线程数量。相比于锁,Semaphore能够更好地支持多线程并发访问,可以更细粒度地控制线程的访问顺序。

Semaphore有两个核心方法,acquire和release。其中acquire用于请求资源,如果资源不可用,线程就会被阻塞。release则用于释放资源。初始化Semaphore实例时需要传入资源个数,Semaphore会根据资源个数决定可以同时访问该资源的线程数量。

Semaphore使用示例

下面我们来看两个使用Semaphore的示例。

示例1:实现限流器

Semaphore的一个常见使用场景是实现限流器。限流器可以控制系统的请求量,也能够防止系统被恶意攻击。例如,在一些API接口返回结果前,我们需要控制每秒钟最多请求多少次API,同一个IP不能请求太频繁。

下面是一个实现限流器的示例:

import java.util.concurrent.Semaphore;

public class RateLimiter {
  private Semaphore semaphore;

  public RateLimiter(int permitsPerSecond) {
    // 每秒生成 permitsPerSecond 个令牌
    semaphore = new Semaphore(permitsPerSecond);
  }

  // 请求资源
  public void acquire() throws InterruptedException {
    semaphore.acquire();
  }

  // 释放资源
  public void release() {
    semaphore.release();
  }
}

在这个示例中,我们创建了一个RateLimiter类,它封装了Semaphore实例。RateLimiter的构造函数需要输入每秒钟生成令牌的个数。在请求资源时,我们使用Semaphore的acquire方法获取令牌。如果没有令牌可以获取,线程就会被阻塞。在释放资源时,我们使用Semaphore的release方法来释放令牌,该令牌就可以被其他线程获取。

示例2:厕所排队

下面我们来看另一个示例,通过Semaphore来模拟厕所排队的场景。假设有5个人需要使用厕所,但是厕所只有2个位置。通过Semaphore来控制同时进入厕所的人数,实现厕所排队的功能。

import java.util.concurrent.Semaphore;

public class Toilet {
  private Semaphore semaphore;

  public Toilet(int limit) {
    semaphore = new Semaphore(limit);
  }

  public void use() throws InterruptedException {
    semaphore.acquire();
    System.out.println(Thread.currentThread().getName() + "进入厕所,剩余位置:" + semaphore.availablePermits());
    Thread.sleep(2000); // 使用一段时间
    System.out.println(Thread.currentThread().getName() + "离开厕所,剩余位置:" + semaphore.availablePermits());
    semaphore.release();
  }
}

public class Main {
  public static void main(String[] args) {
    Toilet toilet = new Toilet(2);

    for (int i = 1; i <= 5; i++) {
      new Thread(() -> {
        try {
          toilet.use();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }, "User" + i).start();
    }
  }
}

在这个示例中,我们创建了一个Toilet类,它封装了Semaphore实例,并且有一个use方法,代表使用厕所的过程。在use方法中,我们先使用Semaphore的acquire方法申请进入厕所。如果已经没有位置,线程就会被阻塞。当进入厕所后,我们使用Thread.sleep方法来让使用时间长一些。最后我们使用Semaphore的release方法离开厕所。

在main函数中,我们创建了5个线程来模拟5个人同时排队进入厕所。在创建Toilet实例时,我们限制了厕所的最大容纳人数为2,使用Semaphore来控制同时在厕所内的人数。

结论

通过上面的两个示例,我们发现Semaphore在控制多线程并发访问时非常有用。Semaphore可以限制线程的访问数量,从而保证异步程序的正确性和性能。Semaphore是Java并发编程中非常常用的一种工具类,建议大家掌握。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程之工具类Semaphore的使用 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • SpringBoot中的响应式web应用详解

    Spring Boot是一个用于构建基于Spring框架开发的应用程序的工具。其提供了快速的应用程序开发和易于使用的API,并确定了一些最佳实践,使得开发人员可以更加专注于应用程序功能和业务逻辑。而“响应式web应用”则是指使用非阻塞I/O的方式,能够更快地处理请求、响应更迅速和更多的请求、更少的资源消耗等特点。 搭建响应式web 应用,我们需要依赖于以下的…

    Java 2023年5月15日
    00
  • Sprint Boot @RestController使用方法详解

    @RestController是Spring Boot中的一个注解,它用于标记一个类,表示该类是一个RESTful风格的控制器。在使用Spring Boot开发Web应用程序时,@RestController是非常重要的。本文将详细介绍@RestController的作用和使用方法,并提供两个示例说明。 @RestController的作用 @RestCon…

    Java 2023年5月5日
    00
  • Spring项目运行依赖spring-contex解析

    Spring框架是个非常流行的Java开发框架,它通过使用依赖注入和面向切面编程等技术来简化Java开发过程。在Spring框架中,spring-context模块是一个非常重要的模块,它提供了一些关键的功能,如依赖注入、AOP和Java EE集成等。在本文中,我们将提供一份完整攻略,从基础到深入,让你了解Spring项目在运行中依赖spring-conte…

    Java 2023年5月20日
    00
  • Java数据类型转换的示例详解

    Java数据类型转换的示例详解 什么是数据类型转换? 在Java中,我们定义变量时需要指定变量的数据类型。不同的数据类型可以存储不同范围内的数值,例如byte类型可以存储从-128到127的整数,而int类型可以存储更大的整数。在程序中,有时需要将一个数据类型的值转换为另一个数据类型的值,这就叫做数据类型转换。 转换类型 Java中数据类型转换分为隐式类型转…

    Java 2023年5月20日
    00
  • 微信小程序获取用户手机号码的详细步骤

    获取微信小程序用户手机号码的详细步骤包括以下三步骤: 用户授权获取手机号码 获取用户信息中的手机号码 解密用户敏感数据以获取手机号码 下面将详细介绍这三步骤。 步骤一:用户授权获取手机号码 用户需要授权小程序获取其手机号码。在小程序中,可以使用<button>或<open-type>来触发获取手机号码的授权。 例如,以下是一个获取用户…

    Java 2023年5月19日
    00
  • 浅谈java面向对象(类,封装,this,构造方法)

    浅谈Java面向对象 类 在Java中,类可看做是一个数据类型,它包含了数据和方法。数据称为类的属性,而方法则是类的行为。 在代码实现中,通过使用关键字“class”来定义一个类,类的命名应遵循驼峰命名法。下面是一个简单的类的定义示例: public class Person { private String name; private int age; p…

    Java 2023年5月26日
    00
  • JavaWeb实现文件上传下载功能实例解析

    JavaWeb实现文件上传下载功能实例解析 一、文件上传 文件上传是指将本地机器上的文件通过网络传输到远程服务器上的过程。在JavaWeb中,可以使用Servlet实现文件上传功能。 在上传文件之前,需要先创建一个表单,让用户选择需要上传的文件。具体操作如下: 在HTML中创建一个表单,指定表单的enctype属性值为”multipart/form-data…

    Java 2023年5月20日
    00
  • sql语句中如何将datetime格式的日期转换为yy-mm-dd格式

    要将Datetime格式的日期转换为yy-mm-dd格式,可以使用SQL语句中的CONVERT()函数。具体步骤如下: 使用CONVERT()函数,将Datetime类型的日期转换为Char类型的日期。语法如下: CONVERT(char(10), [Date], 120) 这里需要解释一下,第二个参数[Date]表示输入的Datetime类型的日期。第三个…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部