悠悠楠杉
Java并发编程:使用Semaphore实现线程交替执行的精确控制,java并发线程代码
正文:
在多线程编程中,控制线程的执行顺序是常见的需求。例如,需要线程A和线程B严格交替执行任务(如A→B→A→B)。Semaphore(信号量)作为Java并发包中的经典同步工具,通过许可证分配机制可实现这种精准控制。本文将揭示其实现原理,并提供可直接落地的代码方案。
一、Semaphore的核心逻辑
Semaphore通过维护一组虚拟许可证控制资源访问:
- acquire():获取许可证(无可用时阻塞)
- release():释放许可证(唤醒等待线程)
通过初始化时分配不同数量的许可证,可控制线程的启动顺序,实现交替执行的核心在于:让两个线程互相等待对方的许可证释放。
二、交替执行的实现设计
假设线程A负责打印数字,线程B负责打印字母,需交替输出1→A→2→B→3→C...。解决方案如下:
1. 创建两个信号量:
- semaphoreA:初始1个许可证(允许线程A先执行)
- semaphoreB:初始0个许可证(阻塞线程B)
2. 线程A执行后释放semaphoreB的许可证
3. 线程B执行后释放semaphoreA的许可证
逻辑闭环:
线程A → 释放B的许可 → 线程B → 释放A的许可 → 线程A...
三、代码实现
java
import java.util.concurrent.Semaphore;
public class AlternateExecution {
private static Semaphore semaphoreA = new Semaphore(1);
private static Semaphore semaphoreB = new Semaphore(0);
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
try {
for (int i = 1; i <= 3; i++) {
semaphoreA.acquire(); // 等待A的许可证
System.out.print(i + "→");
semaphoreB.release(); // 释放B的许可证
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
Thread threadB = new Thread(() -> {
try {
for (char c = 'A'; c <= 'C'; c++) {
semaphoreB.acquire(); // 等待B的许可证
System.out.print(c + "→");
semaphoreA.release(); // 释放A的许可证
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
threadA.start();
threadB.start();
}
}
输出结果:1→A→2→B→3→C→
四、关键点解析
许可证初始化:
semaphoreA初始化为1,确保线程A首先获得执行权semaphoreB初始化为0,使线程B在启动时立即阻塞
释放与获取的对称性:
- 线程A完成任务后释放B的许可证(
semaphoreB.release()) - 线程B完成任务后释放A的许可证(
semaphoreA.release())
- 线程A完成任务后释放B的许可证(
阻塞链的形成:
mermaid graph LR A[线程A] -->|释放B许可| B[线程B] B -->|释放A许可| A
五、扩展应用场景
此模式适用于需严格交替执行的场景:
1. 生产者-消费者模型:单生产者与单消费者的精准协作
2. 多阶段任务处理:如阶段1→阶段2→阶段1的循环工作流
3. 双线程数据校验:线程A生成数据,线程B实时校验
六、注意事项
- 避免死锁:确保
acquire()和release()成对出现 - 许可证数量:初始许可证数量决定启动线程
- 异常处理:在
InterruptedException中正确中断线程
结语
通过Semaphore的许可证请求与释放机制,我们实现了线程间毫秒级的执行顺序控制。这种方案不仅代码简洁,且具备良好的扩展性。理解信号量的核心思想——“许可即权限”,能帮助开发者灵活解决更复杂的并发协作问题。
