Semaphore是什么
信号量(Semaphore),又被称为信号灯,在多线程环境下用于协调各个线程能够正确、合理的使用公共资源。信号量维护了一个许可集,在初始化Semaphore为许可集传入一个数量值,该数量值代表同一时间能访问共享资源的线程数量。
线程可以通过acquire()方法获取到一个许可,然后对共享资源进行操作,注意如果许可集已分配完了,那么线程将进入等待状态,直到其他线程释放许可才有机会再获取许可,线程释放一个许可通过release()方法完成,"许可"将被归还给Semaphore。
类结构
如下图所示,与ReentrantLock一样基于AQS的子类Sync并有公平和非公平模式。Sync继承自AQS,而NonfairSync和FairSync继承自Sync。
再回顾下AQS提供的模板方法:
//独占模式
protected boolean tryAcquire(int arg);
protected boolean tryRelease(int arg);
//共享模式
protected int tryAcquireShared(int arg);
protected boolean tryReleaseShared(int arg);
//判断当前线程是否排它持有state
protected boolean isHeldExclusively();
代码演示
package com.learn.wecath.thread;
import java.util.Date;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
//用static 和final 这样就表明属于类级别的,既然是类级别的,那么可以认为是单例模式的
//也就是最大的并发访问量是3个,即同一时间
//构造参数:
/**
* 1.默认是非公平的,因为里面包含的是一个队列,要实现公平策略,初始化的时候,通过构造函数设置为true,即满足FIFO的原则
* 2.实现单例模式:
* 将Semaphore semaphore = new Semaphore(1),即满足单例模式
*/
private static final Semaphore semaphore = new Semaphore(3);
//并发访问的线程数3个
//创建5个线程,利用线程池,因为创建完线程池,线程的启动即submit()或者execute()就是任务提交和线程启动的一个过程
private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
//静态内部类
private static class InformationThread extends Thread {
//本身是一个普通类,当继承了Thread类之后,就变成一个任务类,即异步处理的类当然他也有自己本身的属性
private final String name;
private final int age;
private InformationThread(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public void run() {
try {
/**
* 通过源码发现:
* acquire有两个方法类型:
* 一个是带参的,限制了获取共享资源的线程数
* 一个是不带参的,没有限制
* 当然是用在run方法中.
*/
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + ":大家好,我是" + name + "我今年" + age + "岁当前时间为:" + System.currentTimeMillis());
Thread.sleep(1000);
System.out.println(name + "要准备释放许可证了,当前时间为:" + new Date());
System.out.println("当前可使用的许可数为:" + semaphore.availablePermits());
semaphore.release();
} catch (Exception e) {
e.getMessage();
}
}
}
public static void main(String[] args) {
String[] name = {"李明", "王五", "张杰", "王强", "赵二", "李四", "张三"};
int[] age = {26, 27, 33, 45, 19, 23, 41};
for (int i = 0; i < 7; i++) {
//创建一个对象的形式;
/**
* 1.利用多态的形式创建---即对象的引用(instanceof)
* 2.利用对象本身创建
*/
Thread thread = new InformationThread(name[i], age[i]);
threadPool.execute(thread);
}
}
}
网友评论