Java并发编程Semaphore计数信号量详解
介绍
Semaphore(信号量)是一个经典的并发编程工具,被广泛应用于各种应用场景,如资源池、限流等。Semaphore 给予我们对并发调度这个宏观的掌控权。
在 Java 5 中,Semaphore 正式被纳入了 Java 并发包,并成为了并发编程中一个必不可少的类。Semaphore 是一个计数信号量,它可以限制同时访问某个资源或者某段代码的线程数量。Semaphore 用于控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理地使用资源。
使用
创建 Semaphore
Semaphore 的创建非常简单,只需要指定信号量的许可数量即可完成。
Semaphore semaphore = new Semaphore(1); // Semaphore 许可数为1
创建一个 Semaphore 实例后,就可以进行 acquire 和 release 操作了。
acquire
acquire(获取许可)方法:当一个线程调用 acquire 操作时,它要么通过获取许可成功获取 Semaphore 许可证,要么一直等下去,直到有许可证可用。Semaphore 有一个许可计数,每调用一次 acquire() 方法许可计数减一,如果计数为零,那么将会等待其他线程释放许可证。
public void acquire() throws InterruptedException
public void acquire(int permits) throws InterruptedException
release
release(释放许可)方法:每调用一次 release() 方法许可证计数加一,然后释放该许可证,以使其可用于其他等待信号量许可证的线程。如果有任何线程试图获取一个许可证,一个释放的许可证将会使它得到许可证,即释放许可证的线程不一定是同一个会获取许可证的线程。
public void release()
public void release(int permits)
示例1
场景:多个线程访问某个资源,但同时只允许两个线程访问。
public class AccessResource {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
Runnable runnable = () -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " access the resource");
Thread.sleep(2000);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
executorService.execute(runnable);
}
executorService.shutdown();
}
}
在上述代码中,创建了一个 Semaphore,许可数量为 2,表示同一时间只有两个线程能够访问资源。然后创建线程池并执行任务。每个任务对Semaphore进行 acquire 和 release 操作,确保同一时间最多只有两个线程能够访问该资源。
示例2
场景:通过 Semaphore 实现简单的限流。
public class RateLimit {
public static void main(String[] args) {
RateLimiter rateLimiter = RateLimiter.create(2);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
Runnable runnable = () -> {
if (rateLimiter.tryAcquire()) {
System.out.println(Thread.currentThread().getName() + " get the access");
} else {
System.out.println(Thread.currentThread().getName() + " rate limit");
}
};
executorService.execute(runnable);
}
executorService.shutdown();
}
}
在上述代码中,使用了一个叫做 RateLimiter 的开源框架实现了限流功能。在使用中通过 Semaphore 控制许可数量,调用 tryAcquire 方法尝试获取许可,如果获取到了就可以进行操作,否则就是限流操作。
总结
Semaphore 是非常常用的工具类,可以方便地实现对资源的控制和访问。需要注意 Semaphore 计数语义和其中与 Mutex 和 ReentrantLock 比较相似的 tryAcquire 方法存在的区别。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发编程Semaphore计数信号量详解 - Python技术站