Java多线程之Semaphore实现信号灯

yizhihongxing

现在我来讲解一下"Java多线程之Semaphore实现信号灯"的完整攻略。在Java多线程编程中,Semaphore可以用来控制多个线程需要访问的资源的数量,Semaphore允许多个线程同时访问某一个资源,但需要限制其同时访问的数量。

Semaphore的基本用法

Semaphore的构造方法:

public Semaphore(int permits)

其中permits表示同时能够访问某一个资源的线程数目。

Semaphore的两个基本方法:

public void acquire() throws InterruptedException
public void release()

其中acquire方法会获取Semaphore的许可,如果没有足够的许可,则会进入等待状态;release方法会释放Semaphore的许可。

Semaphore的应用场景:
Semaphore常用于多个共享资源的互斥使用。例如,读写线程都要访问同一个文件,但是需要限制同时访问该文件的线程数量。

示例一:访问共享资源

下面我们以读写线程访问文件的示例来说明Semaphore的应用。

import java.util.concurrent.Semaphore;

public class ReadWriteFile {
    private Semaphore readSemaphore = new Semaphore(5); // 读许可证
    private Semaphore writeSemaphore = new Semaphore(1); // 写许可证

    public void read() throws InterruptedException {
        readSemaphore.acquire(); // 获取读许可证
        // 读文件
        Thread.sleep(1000);
        System.out.println(Thread.currentThread().getName() + "读了文件");
        readSemaphore.release(); // 释放读许可证
    }

    public void write() throws InterruptedException {
        writeSemaphore.acquire(); // 获取写许可证
        // 写文件
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName() + "写了文件");
        writeSemaphore.release(); // 释放写许可证
    }

    public static void main(String[] args) throws InterruptedException {
        ReadWriteFile rwf = new ReadWriteFile();
        // 多个读线程
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    rwf.read();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "reader " + i).start();
        }
        // 一个写线程
        new Thread(() -> {
            try {
                rwf.write();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "writer").start();
    }
}

上述代码中,read和write方法表示读和写文件。在构造方法中,我们定义了读许可证和写许可证,读许可证可以有5个,写许可证只能有一个。在读文件时,需要读许可证,如果没有足够的读许可证,则线程进入等待状态;在写文件时,需要写许可证,如果没有写许可证,则线程进入等待状态。

上述代码中,我们同时创建10个读线程和1个写线程。根据定义,每次最多只能有5个读线程同时访问文件,只能有一个线程写文件。我们可以运行代码,并观察10个读线程和1个写线程的执行情况。

示例二:限制系统资源

下面我们以限制系统资源数量的示例来说明Semaphore的应用。

import java.util.concurrent.Semaphore;

public class SemaphoreTest {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(2); // 限制系统中最多只能有两个进程并发执行
        // 创建10个线程模拟进程
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire(); // 获取许可证
                    System.out.println(Thread.currentThread().getName() + "获得许可证,开始执行");
                    Thread.sleep(1000); // 模拟进程执行的时间
                    semaphore.release(); // 释放许可证
                    System.out.println(Thread.currentThread().getName() + "释放许可证,执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "Process " + i).start(); // 线程命名为Process0,Process1....Process9
        }
    }
}

上述代码中,Semaphore的初始值为2,表示系统中最多只能有两个进程并发执行。在创建10个线程模拟进程时,每个线程首先获取许可证,如果已经有2个线程在执行,则该线程进入等待状态。当其他线程释放许可证时,当前线程获取到许可证,开始执行进程操作。

上述代码中,我们可以运行代码,并观察10个线程的执行情况。

总结

通过本文的讲解,我们了解了Semaphore在多线程编程中的应用,Semaphore可以用来控制线程对资源的访问数量。Semaphore通过acquire方法获取许可证,通过release方法释放许可证。

在实际应用中,我们可以用Semaphore来实现读写锁、限制系统资源并发执行的数量等。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程之Semaphore实现信号灯 - Python技术站

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

相关文章

  • java实现简易聊天功能

    Java实现简易聊天功能攻略 1. 确定技术栈 要实现简易聊天功能,需要选择合适的技术栈。Java语言比较适合网络编程,因此可以先选择Java语言作为开发语言。 对于通信协议,可以选择TCP或UDP。TCP是一种可靠传输协议,通过三次握手建立连接,确保数据的可靠性。UDP则是一种不可靠传输协议,不进行连接建立,发送数据时没有确认机制。 对于GUI界面,可以使…

    Java 2023年5月19日
    00
  • 终于把 Spring Boot 3.0 写成书了!

    大家好,我是R哥。 我的新书《Spring Boot 3 核心技术与最佳实战》打磨一年多,今天终于上市了,定价 158 元,今天刚上市搞 5 折促销,80 元不到上车,这可能是全网最便宜的时候了,机会难得,想拥抱 Spring Boot 3.0 的不要错过。 文章还没发,已经有老铁粉丝上车了,真爱啊。。。 为什么要学 Spring Boot? Spring …

    Java 2023年4月19日
    00
  • java 判断两个时间段是否重叠的案例

    如何判断两个时间段是否重叠是一个经常遇到的问题。Java提供了多种方式来实现该功能,本篇文章将为大家介绍其中比较常用的两种方案。 方案一:使用Date类和if语句 将两个时间段的起始时间和结束时间分别用Date类表示,并存储在变量中。在Java中,可以使用SimpleDateFormat类将字符串转换为日期类型。 SimpleDateFormat forma…

    Java 2023年5月20日
    00
  • Java多线程-线程的同步与锁的问题

    Java 多线程 – 线程的同步与锁的问题 Java 中,线程的同步与锁是多线程开发中一个极为重要的概念,也是高并发环境下解决数据同步的关键。线程的同步意味着多个线程之间共享数据时需要做到同步,避免数据错乱。锁是线程同步机制的基础,通过加锁可以使线程按照特定的次序串行执行,从而保证多线程访问共享数据时的安全性。 线程同步 当多个线程不同步访问共享数据时,就可…

    Java 2023年5月26日
    00
  • JAVA WEB中Servlet和Servlet容器的区别

    下面是关于“JAVA WEB中Servlet和Servlet容器的区别”的完整攻略。 Servlet的定义 Servlet是Java语言编写的服务器端程序,它可以接受客户端(Web浏览器)的请求并生成响应。Servlet通常被用来扩展Web服务器的功能。简单来说,Servlet是一个服务器端的组件,它能够接受来自客户端的请求,并根据该请求执行相应的任务。 S…

    Java 2023年5月19日
    00
  • 详解Spring Data Jpa当属性为Null也更新的完美解决方案

    下面是详细讲解“详解Spring Data Jpa当属性为Null也更新的完美解决方案”的完整攻略。 1. 背景介绍 在使用Spring Data JPA时,我们通常会遇到这样的情况:当我们更新一个实体时,如果某些属性的值为Null,则这些属性值不会被更新到数据库中。这是因为Spring Data JPA默认情况下只会更新实体中不为Null的属性值。这可能会…

    Java 2023年6月3日
    00
  • Java实现计算一个月有多少天和多少周

    确定一个月有多少天和多少周是一个常见的问题。在Java中可以通过一些基本的语法和时间API来实现。下面我们来详细讲解如何实现计算一个月有多少天和多少周。 计算月份天数 Java中可以使用Calendar类来计算月份天数。具体步骤如下: 获取当前时间,使用Calendar.getInstance()方法获取。例如:Calendar cal = Calendar…

    Java 2023年6月1日
    00
  • java spring整合junit操作(有详细的分析过程)

    下面是详细讲解“Java Spring整合JUnit操作”的攻略,包含以下几个步骤: 添加JUnit依赖库 在项目中添加JUnit依赖库,以使用JUnit框架进行单元测试。在Maven项目中,可以在pom.xml文件中添加以下依赖库: <dependency> <groupId>junit</groupId> <ar…

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