网站首页 > 精选教程 正文
Semaphore 是一种基于计数的信号量,在定义信号量对象的时候可以设置一个阈值,然后基于这个阈值,多线程可以竞争访问信号量,线程竞争到许可的信号之后,开始执行具体的业务逻辑,业务逻辑在执行完成之后释放这个许可信号。
如果许可信号竞争队列超过阈值,新加入的申请信号许可的线程就会被阻塞,知道有其他许可信号被释放。使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
//创建Semaphore信号量,初始化许可大小为3
final Semaphore sp = new Semaphore(3);
for(int i=0;i<10;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e2) {
e2.printStackTrace();
}
Runnable runnable = new Runnable(){
public void run(){
try {
//请求获得许可,如果有可获得的许可则继续往下执行,
//许可数减1。否则进入阻塞状态
sp.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"进入,当前已有" + (3-sp.availablePermits()) + "个并发");
try {
Thread.sleep((long)(Math.random()*10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"即将离开");
sp.release();//释放许可,许可数加1
//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" + Thread.currentThread().getName() +
"已离开,当前已有" + (3-sp.availablePermits()) + "个并发");
}
};
service.execute(runnable);
}
}
}
Semaphore 对于锁的申请与释放和ReentrantLock是类似的,通过acquire()方法和release()方法来获取和释放许可信号资源。
Semaphore.acquire()方法与ReentrantLock.lockInterruptibly()方法的效果是一样的,为可响应中断的锁。也就是说在等待获取许可信号的过程中可以被Thread.interrupt()方法中断而取消对许可信号的申请操作。
除此之外,Semaphore也实现了可轮询的锁请求、定时锁的等功能,以及公平与非公平锁的定义在构造函数中设定
Semaphore锁的释放操作也需要手动进行释放,为此为了避免线程因为异常没有正常释放锁,释放锁的操作必须在finally代码块中完成。
Semaphore也可以用于实现一些对象池、资源池的构建,例如静态全局对象池、数据库连接池等等。
单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
public static void main(String[] args) {
final Business business = new Business();
ExecutorService executor = Executors.newFixedThreadPool(3);
for(int i=0;i<3;i++)
{
executor.execute(
new Runnable()
{
public void run()
{
business.service();
}
}
);
}
executor.shutdown();
}
private static class Business
{
private int count;
Lock lock = new ReentrantLock();
Semaphore sp = new Semaphore(1);
public void service()
{
//lock.lock();
try {
//当前线程使用count变量的时候将其锁住,不允许其他线程访问
sp.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(count);
} catch (RuntimeException e) {
e.printStackTrace();
}
finally
{
//lock.unlock();
sp.release(); //释放锁
}
}
}
}
猜你喜欢
- 2024-11-06 信号量限流,高并发场景不得不说的秘密
- 2024-11-06 面试卡在多线程?那就分享几道Java多线程高频面试题,面试不用愁
- 2024-11-06 Java并发系列之Semaphore源码分析
- 2024-11-06 Java多线程与并发 java的并发,多线程,线程模型
- 2024-11-06 66.java并发编程之Semaphore和CountDownLatch使用
- 2024-11-06 Java基础笔试练习(十五) java基础知识试题
- 2024-11-06 72道Java线程面试题,这些面试官必问
- 2024-11-06 Java并发基础-锁详细分析(可重入锁、读写锁、信号量等)
- 2024-11-06 Java并发工具:CountDownLatch CyclicBarrier Semaphore快速掌握
- 2024-11-06 死磕 java同步系列之Semaphore源码解析
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)