Semaphore的使用

简介:

  Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。

Semaphore的主要方法摘要:

  void acquire()**:**从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。

  void release():释放一个许可,将其返回给信号量。

  int availablePermits():返回此信号量中当前可用的许可数。

  boolean hasQueuedThreads():查询是否有线程正在等待获取。

下面是一个例子:


 1 package com.thread;
 2
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 import java.util.concurrent.Semaphore;
 6
 7 public class SemaphoreTest {
 8     public static void main(String[] args) {
 9         ExecutorService service = Executors.newCachedThreadPool();
10         final  Semaphore sp = new Semaphore(3);//创建Semaphore信号量,初始化许可大小为3
11         for(int i=0;i<10;i++){
12             try {
13                 Thread.sleep(100);
14             } catch (InterruptedException e2) {
15                 e2.printStackTrace();
16             }
17             Runnable runnable = new Runnable(){
18                     public void run(){
19                     try {
20                         sp.acquire();//请求获得许可,如果有可获得的许可则继续往下执行,许可数减1。否则进入阻塞状态
21                     } catch (InterruptedException e1) {
22                         e1.printStackTrace();
23                     }
24                     System.out.println(“线程” + Thread.currentThread().getName() +
25                             “进入,当前已有” + (3-sp.availablePermits()) + “个并发”);
26                     try {
27                         Thread.sleep((long)(Math.random()*10000));
28                     } catch (InterruptedException e) {
29                         e.printStackTrace();
30                     }
31                     System.out.println(“线程” + Thread.currentThread().getName() +
32                             “即将离开”);
33                     sp.release();//释放许可,许可数加1
34                     //下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
35                     System.out.println(“线程” + Thread.currentThread().getName() +
36                             “已离开,当前已有” + (3-sp.availablePermits()) + “个并发”);
37                 }
38             };
39             service.execute(runnable);
40         }
41     }
42
43 }

  单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。
 1 package com.thread;
 2 import java.util.concurrent.ExecutorService;
 3 import java.util.concurrent.Executors;
 4 import java.util.concurrent.Semaphore;
 5 import java.util.concurrent.locks.Lock;
 6 import java.util.concurrent.locks.ReentrantLock;
 7
 8 public class LockTest {
 9     public static void main(String[] args) {
10         final Business business = new Business();
11         ExecutorService executor =  Executors.newFixedThreadPool(3);
12         for(int i=0;i<3;i++)
13         {
14             executor.execute(
15                     new Runnable()
16                     {
17                         public void run()
18                         {
19                             business.service();
20                         }
21                     }
22
23             );
24         }
25         executor.shutdown();
26     }
27
28     private static class Business
29     {
30         private int count;
31         Lock lock = new ReentrantLock();
32         Semaphore sp = new Semaphore(1);
33         public void service()
34         {
35             //lock.lock();
36             try {
37                 sp.acquire(); //当前线程使用count变量的时候将其锁住,不允许其他线程访问
38             } catch (InterruptedException e1) {
39                 e1.printStackTrace();
40             }
41             try {
42                 count++;
43                 try {
44                     Thread.sleep(1000);
45                 } catch (InterruptedException e) {
46                     e.printStackTrace();
47                 }
48                 System.out.println(count);
49             } catch (RuntimeException e) {
50                 e.printStackTrace();
51             }
52             finally
53             {
54                 //lock.unlock();
55                 sp.release();  //释放锁
56             }
57         }
58     }
59
60 }

相关文章
|
SQL 运维 安全
闲鱼交易实时资损防控体系
聊一聊资损防控体系和闲鱼实践
6661 0
闲鱼交易实时资损防控体系
|
10月前
|
机器学习/深度学习 测试技术 知识图谱
DeepSeek-R1:Incentivizing Reasoning Capability in LLMs via Reinforcement Learning论文解读
DeepSeek团队推出了第一代推理模型DeepSeek-R1-Zero和DeepSeek-R1。DeepSeek-R1-Zero通过大规模强化学习训练,展示了卓越的推理能力,但存在可读性和语言混合问题。为此,团队引入多阶段训练和冷启动数据,推出性能与OpenAI-o1-1217相当的DeepSeek-R1,并开源了多个密集模型。实验表明,DeepSeek-R1在多项任务上表现出色,尤其在编码任务上超越多数模型。未来研究将聚焦提升通用能力和优化提示工程等方向。
722 16
|
SQL 数据管理 关系型数据库
《SQL转换秘籍:Vanna+Qwen双剑合璧,轻松实现私有模型转换》——揭秘如何利用Vanna和Qwen这两款神级工具,让你的SQL数据管理和转换如虎添翼!
【8月更文挑战第17天】Vanna与Qwen是两款优秀的开源数据库管理工具,助力用户高效管理及转换SQL数据。先安装Vanna和Qwen,随后在Vanna中创建并编辑私有模型,定义表结构等。完成模型构建后,导出为SQL文件。接着,在Qwen中导入此文件,并根据目标数据库类型(如MySQL)转换SQL语句。例如,生成创建`users`表的SQL代码。这两款工具显著提升了数据库管理工作流程的便捷性与效率。
723 1
Ngnix17---Ngnix服务的信号控制值USR2
Ngnix17---Ngnix服务的信号控制值USR2
|
运维 关系型数据库 MySQL
Ansible自动化运维工具主机清单配置
Ansible自动化运维工具主机清单配置
411 0
多线程并发之Semaphore(信号量)使用详解
多线程并发之Semaphore(信号量)使用详解
5666 0
|
数据安全/隐私保护 Docker 容器
快速搭建最新版ansible-AWX
本文主要内容为简单搭建ansible-AWX的流程,AWX是社区版、商业版叫TOWER
|
SQL 存储 JSON
日处理消息2亿,通过核对体系做资损防控的技术挑战
日处理消息2亿,通过核对体系做资损防控的技术挑战
785 0
|
Linux 关系型数据库 Oracle
|
存储 监控 Java
非侵入式AOP监控之——AspectJ使用
> 一引言 > 二什么是AspectJ > 2.1 它只是一个代码编译器 > 2.2 它是用来做AOP编程的 > 2.3为什么要用AspectJ > 三AspectJ原理与运用 > 3.1 基本原理 > 3.2 使用方式 > 3.2.1 纯注解方式 > 3.2.2 AspectJ语言 > 3.2.3 结合自定义注解使用 > 四 使用AspectJ进行监听方法执行耗时 > 五
10358 0