zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java Semaphore

JAVA Semaphore
2023-09-11 14:22:55 时间

Oracle 官方文档

http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html

package java.util.concurrent.Semaphore;

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.

Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource. For example, here is a class that uses a semaphore to control access to a pool of items:

一个计数信号量。从概念上来看,一个信号量维护了一套许可证。如果必要的话,每一个acquire方法都会阻塞,直到许可证可用并且拿到为止。每一个release方法都会添加一个许可证,潜在地释放一个阻塞的收购者。然而,没有使用实际的许可对象,Semaphore只是持有了一定数量的可用值并采取相应的行动。

Semaphores通常被用于限制可以访问(物理的或者逻辑的)资源的线程的数量。举个例子,这里是一个类,使用信号量来控制池子里的对象。

构造函数

  • public Semaphore(int permits) {……}
  • public Semaphore(int permits, boolean fair) {……}

使用给定数目的许可证和是否公平的设置创建一个信号量。

  • 参数permits
    指定初始的可用许可证数量。该值可以为负,这样就只能先执行release操作,然后acquire操作才会被允许。
  • 参数fair
    默认为false,该属性为true,表示该信号量在竞争的环境中依然保证先进先出的获得许可证。否则为false。
/**
 * Creates a {@code Semaphore} with the given number of
 * permits and nonfair fairness setting.
 *
 * @param permits the initial number of permits available.
 *        This value may be negative, in which case releases
 *        must occur before any acquires will be granted.
 */
public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}

/**
 * Creates a {@code Semaphore} with the given number of
 * permits and the given fairness setting.
 *
 * @param permits the initial number of permits available.
 *        This value may be negative, in which case releases
 *        must occur before any acquires will be granted.
 * @param fair {@code true} if this semaphore will guarantee
 *        first-in first-out granting of permits under contention,
 *        else {@code false}
 */
public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}

测试用例

package com.demo.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreDemo {

    public static void main(String[] args) {
        //有6个人去WC,但厕所只有3个坑位,因此要排队使用
        final int PERMITS = 3;
        final int N_THREADS = 6;
        final Semaphore semaphore = new Semaphore(PERMITS);
        ExecutorService executorService = Executors.newFixedThreadPool(N_THREADS);
        for (int i = 0; i < N_THREADS; i++) {
            final int NO = i+1;
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    boolean isAcquire = false;
                    try {
                        System.out.println("NO."+ NO + " wait");
                        semaphore.acquire();
                        System.out.println("NO."+ NO + " enter");
                        isAcquire = true;
                        Thread.sleep((long) (Math.random() * 1000));
                        System.out.println("NO."+ NO + " out");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        if (isAcquire) {
                            semaphore.release();
                        }
                    }
                }
            });
        }
    }
}

运行结果

NO.1 wait
NO.1 enter
NO.2 wait
NO.2 enter
NO.5 wait
NO.6 wait
NO.4 wait
NO.5 enter
NO.3 wait
NO.2 out
NO.6 enter
NO.1 out
NO.4 enter
NO.5 out
NO.3 enter
NO.6 out
NO.3 out
NO.4 out