Java并发编程(8)-Semaphore

释放双眼,带上耳机,听听看~!

文章目录

  • 一、Semaphore信号量

  • 1.1、什么是信号量
    * 1.2、信号量在并发编程中的作用

    
    
    1
    2
    1  * 二、Semaphore类简单解读
    2
  • 2.1、构造方法解读
    * 2.2、常用方法解读

    
    
    1
    2
    3
    1  * 三、简单程序解读
    2  * 四、公平模式和非公平模式
    3


在Java并发编程中,信号量(Semaphore类)可视为synchronized的升级,它能控制一个程序中线程的数量,负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

一、Semaphore信号量

1.1、什么是信号量

以一个停车场是运作为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操作时,它要么通过然后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为加操作实际上是释放了由信号量守护的资源。
在java中,还可以设置该信号量是否采用公平模式,如果以公平方式执行,则线程将会按到达的顺序(FIFO)执行,如果是非公平,则可以后请求的有可能排在队列的头部
JDK中定义如下:
Semaphore(int permits, boolean fair)
创建具有给定的许可数和给定的公平设置的Semaphore。 –百度百科

1.2、信号量在并发编程中的作用

在Java并发编程中,信号量(Semaphore类)可视为synchronized的升级,它能控制一个程序中线程的数量,负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

二、Semaphore类简单解读

Semaphore类位于java.util.concurrent并发包之下,它是信号量的具体实现类。

2.1、构造方法解读

(1)、public Semaphore(int permits)
用给定的许可数和非公平的公平设置创建一个 Semaphore,即线程不按照FIFO的方式执行。

参数:
permits – 初始的可用许可数目。此值可能为负数,在这种情况下,必须在授予任何获取前进行释放。

(2)、public Semaphore(int permits, boolean fair)
用给定的许可数和给定的公平设置创建一个 Semaphore,保证线程的执行是FIFO方式的。

参数:
permits – 初始的可用许可数目。此值可能为负数,在这种情况下,必须在授予任何获取前进行释放。
fair – 如果此信号量保证在争用时按先进先出的顺序授予许可,则为 ture,否则为 false。

2.2、常用方法解读

(1)、acquire方法
public void acquire() throws InterruptedException
从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。 获取一个许可(如果提供了一个)并立即返回,将可用的许可数减 1。
如果没有可用的许可,则在发生以下两种情况之一前,禁止将当前线程用于线程安排目的并使其处于休眠状态:

某些其他线程调用此信号量的 release() 方法,并且当前线程是下一个要被分配许可的线程;
②其他某些线程中断当前线程

(2)、tryAcquire方法
①public boolean tryAcquire()
仅在调用时此信号量存在一个可用许可,才从信号量获取许可。
获取一个许可(如果提供了一个)并立即返回,其值为 true,将可用的许可数减 1。 如果没有可用的许可,则此方法立即返回并且值为 false。

② public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException
如果在给定的等待时间内此信号量有可用的所有许可,并且当前线程未被中断,则从此信号量获取给定数目的许可。
获取给定数目的许可(如果提供了)并立即返回,其值为 true,将可用的许可数减去给定的量。

如果没有足够的可用许可,则在发生以下三种情况之一前,禁止将当前线程用于线程安排目的并使其处于休眠状态:

①其他某些线程调用此信号量的某个释放方法,当前线程是下一个被分配许可的线程,并且可用许可的数目满足此请求;

②其他某些线程中断当前线程;

③ 已超出指定的等待时间。

(3)、availablePermits方法
public int availablePermits()
返回此信号量中当前可用的许可数。 此方法通常用于调试和测试目的。

(4)、release方法
public void release(int permits)
释放给定数目的许可,将其返回到信号量。
释放给定数目的许可,将可用的许可数增加该量。如果任意线程试图获取许可,则选中某个线程并将刚刚释放的许可给予该线程。如果可用许可的数目满足该线程的请求,则针对线程安排目的启用(或再启用)该线程;否则在有足够的可用许可前线程将一直等待。如果满足此线程的请求后仍有可用的许可,则依次将这些许可分配给试图获取许可的其他线程。

三、简单程序解读


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1@Test
2    public void semaphoreTest(){
3        Semaphore semaphore = new Semaphore(3);
4
5        ExecutorService executorService = Executors.newFixedThreadPool(2);
6        for (int i = 0; i < 5; i++) {
7            executorService.execute(new Runnable(){
8                Semaphore semaphore1 = semaphore;
9                public void run(){
10
11                    try {
12                        semaphore1.acquire();//获取信号量,执行程序
13                        System.out.println(Thread.currentThread().getName()+"获得信号量,开始执行程序...,剩余信号量:"+semaphore1.availablePermits());
14                    } catch (InterruptedException e) {
15                        e.printStackTrace();
16                    }finally {
17                        semaphore1.release();//释放信号量
18                        System.out.println("线程"+Thread.currentThread().getName()+"释放信号量,剩余信号量:"+semaphore1.availablePermits());
19                    }
20
21                }
22            });
23        }
24    }
25
26

Java并发编程(8)-Semaphore如果我们不释放信号量。那么3信号量被消耗完,程序也就是循环到第3次的时候,程序就已经结束了,因为没有信号量,线程也就没有权利执行程序。


1
2
3
4
5
6
7
8
1       finally {
2                       // semaphore1.release();//释放信号量
3                        //System.out.println("线程"+Thread.currentThread().getName()+"释放信号量,剩余信号量:"+semaphore1.availablePermits());
4                        System.out.println("剩余信号量:"+semaphore1.availablePermits());
5
6                    }
7
8

Java并发编程(8)-Semaphore

四、公平模式和非公平模式

1.公平模式

根据acquire的顺序来获取许可证,遵循FIFO。

2.非公平模式

即抢占式获取许可证。这是默认情况。

可在构造信号量时通过构造函数去设置这两种模式:


1
2
3
4
5
6
7
8
9
10
11
1    // 默认是非公平的
2    public Semaphore(int permits) {
3        sync = new NonfairSync(permits);
4    }
5
6    public Semaphore(int permits, boolean fair) {
7        sync = fair ? new FairSync(permits) : new NonfairSync(permits);
8    }
9
10
11

给TA打赏
共{{data.count}}人
人已打赏
安全技术

详解Node.js API系列 Crypto加密模块(1)

2021-12-21 16:36:11

安全技术

从零搭建自己的SpringBoot后台框架(二十三)

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索