并发工具类之Semaphore
2020-11-27 本文已影响0人
逍遥白亦
Semaphore(信号量)
定义
先看Java API中的定义
A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it. Each release() adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly.
一个计数信号量。 在概念上,信号量维持一组许可证。 如果有必要,每个acquire()都会阻塞,直到许可证可用,然后才能使用它。 每个release()添加许可证,潜在地释放阻塞获取方。 但是,没有使用实际的许可证对象; Semaphore只保留可用数量的计数,并相应地执行。
官方的例子
信号量通常用于限制线程数,而不是访问某些(物理或逻辑)资源。 例如,这是一个使用信号量来控制对一个项目池的访问的类:
class Pool {
private static final int MAX_AVAILABLE = 100;
private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
public Object getItem() throws InterruptedException {
available.acquire();
return getNextAvailableItem();
}
public void putItem(Object x) {
if (markAsUnused(x))
available.release();
}
// Not a particularly efficient data structure; just for demo
protected Object[] items = ... whatever kinds of items being managed
protected boolean[] used = new boolean[MAX_AVAILABLE];
protected synchronized Object getNextAvailableItem() {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (!used[i]) {
used[i] = true;
return items[i];
}
}
return null; // not reached
}
protected synchronized boolean markAsUnused(Object item) {
for (int i = 0; i < MAX_AVAILABLE; ++i) {
if (item == items[i]) {
if (used[i]) {
used[i] = false;
return true;
} else
return false;
}
}
return false;
}
}
具体引用
在日常生活中,一些特别好吃的饭馆在饭点儿的时候,都需要等位,假设餐馆一共可以容纳30个顾客,而一共有100位顾客想要吃饭,如何有序的让所有顾客都能吃上饭呢?
可以试着用信号量来试试。
package SemaphoreTest;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* 顾客类
*/
public class Customer implements Runnable {
private int id;
private Semaphore semaphore;
private static Random random = new Random(30);
public Customer(int id, Semaphore semaphore) {
this.id = id;
this.semaphore = semaphore;
}
public void run() {
try {
semaphore.acquire();
System.out.println(this.id + "having dinner");
TimeUnit.MILLISECONDS.sleep(random.nextInt(2000));
semaphore.release();
System.out.println(this.id + "is leaving");
} catch (InterruptedException e){
System.out.println(Arrays.toString(e.getStackTrace()));
}
}
}
package SemaphoreTest;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class Restaurant {
private static int customerCount = 100;
private static Semaphore semaphore = new Semaphore(30);
private static ExecutorService threadPool = Executors.newFixedThreadPool(customerCount);
public static void main(String[] args) {
for (int i = 0; i < customerCount; i++){
threadPool.execute(new Customer(i, semaphore));
}
threadPool.shutdown();
}
}