SemaphoreDemo案例

Semaphore 是 Java 并发包中的一种同步工具,它主要用于控制同时访问特定资源或执行特定操作的线程数量。以下是 Semaphore 的主要作用和特点:

  1. 控制并发线程数量: Semaphore 可以限制同时访问某一资源或执行某一操作的线程数量,通过设置信号量的计数器来实现控制。

  2. 资源池的控制: 可以用于实现对象池、连接池等场景,限制池中资源的并发访问数量。

  3. 保护共享资源: 可以保护共享资源不被多个线程同时访问,从而避免竞态条件和数据不一致性问题。

  4. 实现互斥访问: 类似于锁的功能,但比锁更灵活,可以控制多个线程同时访问某个资源的数量。

  5. 实现公平性: Semaphore 可以选择是否公平地分配许可,即先请求许可的线程将获得许可的优先权。

在使用 Semaphore 时,主要涉及到两个核心方法:

  • acquire():请求一个许可,如果没有许可可用,则阻塞直到有许可可用。
  • release():释放一个许可,使其可供其他线程使用。

通过初始化 Semaphore 实例时设定的许可数量,可以控制同时允许多少个线程执行关键代码段或访问关键资源。当许可数量为 1 时,Semaphore 的行为类似于互斥锁(Mutex),允许只有一个线程访问临界区;当许可数量大于 1 时,多个线程可以同时访问临界区,但受许可数量的限制。

下面举一个关于停车场的例子,当有车离开时,会有另一辆车抢到位置

import java.util.concurrent.Semaphore; 
import java.util.concurrent.TimeUnit; 
public class SemaphoreDemo { 
	public static void main(String[] args) { 
		Semaphore semaphore = new Semaphore(2); 
		for (int i = 0; i < 10; i++) { 
			Thread t = new Thread(() -> { 
				try { 
					semaphore.acquire(); 
				} catch (InterruptedException e) { 
					e.printStackTrace();
	 	    	} 
				System.out.println(Thread.currentThread().getName() + " : 抢到位置"); 
				try { 
					TimeUnit.SECONDS.sleep(5); 
				} catch (InterruptedException e) { 
					e.printStackTrace(); 
				} 
				semaphore.release(); 
				System.out.println(Thread.currentThread().getName() + " : 离开位置"); 
			});
	 		t.start(); 
		} 
	} 
} 

感谢您的阅读!有任何疑问,欢迎联系我
714321862@qq.com

### Java Semaphore 的实现与用法 `Semaphore` 是一种用于控制并发访问的同步工具,它可以限制同时访问某一资源的线程数量。以下是 `Semaphore` 类的一个简单实现及其用法。 #### 1. 基本概念 `Semaphore` 使用一组许可证来管理对共享资源的访问。当某个线程需要访问受保护的资源时,它必须先从 `Semaphore` 中获取一个许可。如果此时没有可用的许可,则该线程会被阻塞直到有许可被释放[^1]。 #### 2. 核心方法 - **acquire()**: 获取一个许可。如果没有可用的许可,则当前线程会被阻塞。 - **release()**: 释放一个许可,从而允许其他等待中的线程继续运行。 - **availablePermits()**: 返回当前可用的许可数。 #### 3. 示例代码 下面是一个简单的 `SemaphoreDemo` 实现: ```java import java.util.concurrent.Semaphore; public class SemaphoreDemo { public static void main(String[] args) { // 创建一个具有两个许可的信号量实例 Semaphore semaphore = new Semaphore(2); Runnable task = () -> { try { System.out.println(Thread.currentThread().getName() + " is waiting for a permit."); // 尝试获取一个许可 semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " acquires a permit."); // 模拟任务处理时间 Thread.sleep((long)(Math.random() * 1000)); } catch (InterruptedException e) { System.err.println(e.getMessage()); } finally { // 完成任务后释放许可 semaphore.release(); System.out.println(Thread.currentThread().getName() + " releases a permit."); } }; // 创建多个线程并启动它们 for (int i = 0; i < 5; i++) { new Thread(task).start(); } } } ``` 在这个例子中: - 我们创建了一个初始有两个许可的 `Semaphore` 对象。 - 多个线程试图获取这些许可。由于只有两个许可存在,因此最多可以有两个线程同时执行临界区的任务。 - 当线程完成其工作后,调用 `semaphore.release()` 方法释放许可,以便其他正在等待的线程能够获得许可并继续执行。 #### 4. 并发场景下的行为分析 在多线程环境中,`Semaphore` 可以用来协调不同线程之间的操作顺序。例如,在数据库连接池或者文件读写器的数量受限的情况下,可以通过设置合适的许可数目来防止过多的线程争抢有限的资源[^2]。 对于公平性和非公平性的选择,默认情况下是非公平模式(即不按照请求顺序分配),但如果希望优先考虑较早到达的线程,则可以在构造函数中指定参数 `true` 来启用公平模式。 #### 5. 错误处理机制 需要注意的是,如果在线程持有许可期间发生异常而未显式调用 `release()` 函数的话,可能会导致死锁情况的发生。为了避免这种情况,建议总是把 `release()` 放置在一个 `finally` 块里,就像上面的例子那样做[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小江小河点、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值