写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
概念:
Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制。从概念上讲,Semaphore是一个计数信号量,Semaphore包含一组许可证。
如果有需要的话,每个acquire()方法都会阻塞,直到获取一个可用的许可证。每个release()方法都会释放持有许可证的线程,并且归还Semaphore一个可用的许可证。
使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。
Semaphore 是 synchronized 的加强版,作用是控制同时访问资源的线程个数(控制线程的并发数量)
当Semaphore初始值为1时其实就相当于 synchronized。
常用方法:
1.Semaphore(permits)
初始化许可证数量的构造函数。
2.Semaphore(permits,fair)
初始化许可证数量和是否公平模式的构造函数。
3.availablePermits()
获取当前可用的许可证数量。
4.acquire()
当前线程尝试去获取1个许可证。直到发生以下任意一件事:
1):当前线程获取了1个可用的许可证,则会停止等待,继续执行。
2):当前线程被中断,则会抛出InterruptedException异常,并停止等待,继续执行。
5.acquire(permits)
当前线程尝试去获取permits个许可证。直到发生以下任意一件事:
1):当前线程获取了permits个可用的许可证,则会停止等待,继续执行。
2):当前线程被中断,则会抛出InterruptedException异常,并停止等待,继续执行。
6.tryAcquire()
当前线程尝试去获取1个许可证。
1):如果当前线程获取了1个可用的许可证,则会停止等待,继续执行,并返回true。
2):如果当前线程没有获得这个许可证,也会停止等待,继续执行,并返回false。
7.tryAcquire(permits)
当前线程尝试去获取permits个许可证。
1):如果当前线程获取了permits个可用的许可证,则会停止等待,继续执行,并返回true。
2):如果当前线程没有获得permits个许可证,也会停止等待,继续执行,并返回false。
8.tryAcquire(timeout,TimeUnit)
当前线程在限定时间内,尝试去获取1个许可证。直到发生以下任意一件事:
1):当前线程获取了可用的许可证,则会停止等待,继续执行,并返回true。
2):当前线程等待时间timeout超时,则会停止等待,继续执行,并返回false。
3):当前线程在timeout时间内被中断,则会抛出InterruptedException一次,并停止等待,继续执行。
9.tryAcquire(permits,timeout,TimeUnit)
当前线程在限定时间内,尝试去获取permits个许可证。直到发生以下任意一件事:
1):当前线程获取了可用的permits个许可证,则会停止等待,继续执行,并返回true。
2):当前线程等待时间timeout超时,则会停止等待,继续执行,并返回false。
3):当前线程在timeout时间内被中断,则会抛出InterruptedException一次,并停止等待,继续执行。
10.release()
当前线程释放1个可用的许可证。
11.release(permits)
当前线程释放permits个可用的许可证。
因为平时用的不多,就简单举例记录一下,这个例子包含3个类,一个是线程类,一个是 线程要操作的资源类,一个类是主main方法类:
代码如下:
public class SemaphoreTest {public static void main(String[] args) {DoSomething doSomething &#61; new DoSomething();for (int i&#61;0;i<10;i&#43;&#43;){Task t &#61; new Task(doSomething);t.start();}}static class DoSomething{Semaphore semaphore &#61; new Semaphore(2);public void doSome(){try {semaphore.acquire();System.out.println(Thread.currentThread().getName() &#43; ":开始任务");Thread.sleep(2000);System.out.println(Thread.currentThread().getName() &#43; ":完成任务");semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}}static class Task extends Thread{private DoSomething doSomething;public Task(DoSomething doSomething){this.doSomething &#61; doSomething;}&#64;Overridepublic void run() {doSomething.doSome();}}}
执行结果如下&#xff1a;
可以看出&#xff1a;每次只能有两个线程并行执行&#xff0c;正如前面所说&#xff0c;它的作用就是控制同时访问资源的线程个数&#xff0c;一次只允许permits个线程访问。