Java信号量Semaphore原理及代码实例

 更新时间:2020年10月19日 09:45:53   作者:cuisuqiang  
这篇文章主要介绍了Java信号量Semaphore原理及代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。自从5.0开始,jdk在java.util.concurrent包里提供了Semaphore 的官方实现,因此大家不需要自己去实现Semaphore。

下面的类使用信号量控制对内容池的访问:

import java.util.concurrent.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(); // 释放一个许可,将其返回给信号量 
  } 
  // 仅作示例参考,非真实数据 
  protected Object[] items = null; 
  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; 
  } 
  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; 
  } 
} 

虽然JDK已经提供了相关实现,但是还是很有必要去熟悉如何使用Semaphore及其背后的原理。
做一个简单的Semaphore实现:

class SemaphoreTest { 
  private boolean signal = false; 
  public synchronized void take() { 
    this.signal = true; 
    this.notify(); 
  } 
  public synchronized void release() throws InterruptedException { 
    while (!this.signal) 
      wait(); 
    this.signal = false; 
  } 
} 

使用这个semaphore可以避免错失某些信号通知。用take方法来代替notify,release方法来代替wait。如果某线程在调用release等待之前调用take方法,那么调用release方法的线程仍然知道take方法已经被某个线程调用过了,因为该Semaphore内部保存了take方法发出的信号。而wait和notify方法就没有这样的功能。

可计数的Semaphore:

class SemaphoreTest { 
  private int signals = 0; 
  public synchronized void take() { 
    this.signals++; 
    this.notify(); 
  } 
  public synchronized void release() throws InterruptedException { 
    while (this.signals == 0) 
      wait(); 
    this.signals--; 
  } 
} 

Semaphore上限:

class SemaphoreTest {
	private int signals = 0;
	private int bound = 0;
	public SemaphoreTest(int upperBound) {
		this.bound = upperBound;
	}
	public synchronized void take() throws InterruptedException {
		while (this.signals == bound)
			wait();
		this.signals++;
		this.notify();
	}
	public synchronized void release() throws InterruptedException {
		while (this.signals == 0)
			wait();
		this.signals--;
		this.notify();
	}
}

当已经产生的信号数量达到了上限,take方法将阻塞新的信号产生请求,直到某个线程调用release方法后,被阻塞于take方法的线程才能传递自己的信号。

把Semaphore当锁来使用:

当信号量的数量上限是1时,Semaphore可以被当做锁来使用。通过take和release方法来保护关键区域。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • java常用数据流应用实例解析

    java常用数据流应用实例解析

    这篇文章主要介绍了java常用数据流应用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • 每天学Java!一分钟了解JRE与JDK

    每天学Java!一分钟了解JRE与JDK

    每天学Java!一分钟了解JRE与JDK,什么是JRE?什么是JDK?什么是JVM?相信通过本文大家都会有所了解,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • Spring Validation实现数据校验的示例

    Spring Validation实现数据校验的示例

    Spring Validation其实就是对Hibernate Validator进一步的封装,方便在Spring中使用,这篇文章主要介绍了Spring Validation实现数据校验的示例,需要的朋友可以参考下
    2023-03-03
  • Spring Boot配置特定属性spring.profiles的方法

    Spring Boot配置特定属性spring.profiles的方法

    这篇文章主要介绍了Spring Boot配置特定属性spring.profiles的方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-11-11
  • Java中值传递和引用传递的区别

    Java中值传递和引用传递的区别

    这篇文章主要介绍了Java中值传递和引用传递的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • 使用springboot 打包插件去除jar包瘦身

    使用springboot 打包插件去除jar包瘦身

    这篇文章主要介绍了使用springboot 打包插件去除jar包瘦身的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • java9开始——接口中可以定义private私有方法

    java9开始——接口中可以定义private私有方法

    这篇文章主要介绍了从java9开始 接口中可以定义private私有方法,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-10-10
  • Java MyBatis 多表查询详解

    Java MyBatis 多表查询详解

    这篇文章主要给大家介绍了关于MyBatis如何实现多表查询(多对一、一对多)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习
    2021-09-09
  • Java Excel数据导入数据库的方法

    Java Excel数据导入数据库的方法

    这篇文章主要为大家详细介绍了Java Excel数据导入数据库,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • servlet过滤器(Filter)详解(九)

    servlet过滤器(Filter)详解(九)

    这篇文章主要为大家详细介绍了servlet过滤器Filter的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09

最新评论