并发工具类之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();

    }
}

上一篇下一篇

猜你喜欢

热点阅读