侧边栏壁纸
博主头像
再见理想博主等级

只争朝夕,不负韶华

  • 累计撰写 112 篇文章
  • 累计创建 64 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Semaphore 信号量

再见理想
2022-05-29 / 0 评论 / 0 点赞 / 294 阅读 / 760 字

一,简介

Semaphore 允许一定数量线程同时访问临界区资源。

二,构造函数

在构造信号量对象时,须指定信号量的准入数,即同时能申请多少个许可。当每个线程每次只能申请一个许可时,就相当于指定了同时有多少个线程可以访问某一资源。

/**
     * 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);
    }

三,主要方法

acquire()

方法尝试获得一个准入的许可。若无法获得,则线程会等待,直到有线程释放一个许可或者当前线程被中断。

acquireUninterruptibly()

方法和 acquire 方法类似,但是不响应中断。

tryAcquire()

尝试获得一个许可,如果成功返回 true,失败则返回 false,它不会进行等待,立即返回。

release()

用于在线程访问资源结束后,释放一个许可,以使其他等待许可的线程可以进行资源访问。

四,简单使用

import cn.hutool.core.date.DateUtil;

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

public class SemaphoreDemo implements Runnable {

	//创建信号量实例,指定准入数为5
    final Semaphore semp = new Semaphore(5);

    @Override
    public void run() {
        try {
            //获取许可,若得到许可再继续执行
            semp.acquire();
            //模拟耗时操作
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + ":done!" + DateUtil.formatDateTime(new Date()));
            //释放许可
            semp.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newFixedThreadPool(20);
        final SemaphoreDemo demo = new SemaphoreDemo();
        for (int i = 0; i < 20; i++) {
            exec.submit(demo);
        }
        exec.shutdown();
    }
}

结果打印:

pool-1-thread-2:done!2021-05-12 11:58:45
pool-1-thread-1:done!2021-05-12 11:58:45
pool-1-thread-5:done!2021-05-12 11:58:45
pool-1-thread-9:done!2021-05-12 11:58:45
pool-1-thread-13:done!2021-05-12 11:58:45
pool-1-thread-17:done!2021-05-12 11:58:47
pool-1-thread-6:done!2021-05-12 11:58:47
pool-1-thread-14:done!2021-05-12 11:58:47
pool-1-thread-18:done!2021-05-12 11:58:47
pool-1-thread-10:done!2021-05-12 11:58:47
pool-1-thread-7:done!2021-05-12 11:58:49
pool-1-thread-3:done!2021-05-12 11:58:49
pool-1-thread-11:done!2021-05-12 11:58:49
pool-1-thread-15:done!2021-05-12 11:58:49
pool-1-thread-19:done!2021-05-12 11:58:49
pool-1-thread-12:done!2021-05-12 11:58:51
pool-1-thread-4:done!2021-05-12 11:58:51
pool-1-thread-8:done!2021-05-12 11:58:51
pool-1-thread-16:done!2021-05-12 11:58:51
pool-1-thread-20:done!2021-05-12 11:58:51

可以看到,最多有5个线程同时打印。

0

评论区