JAVA多线程之Semaphore
Semaphore:动态增减信号量,用于控制对某资源访问的同一时间的并发量。类似于令牌,谁拿到令牌(acquire)就可以去执行了,如果没有令牌则需要等待。
【如何获取】:
semaphore.tryAcquire(),尝试获取,不阻塞。
semaphore.acquire(),没信号量可用时,将进行阻塞等,可以被中断。
acquireUninterruptibly():获取信号量,将进行阻塞,但会忽略线程的中断而且不会抛出任何异常。
【如何释放】:
semaphore.release();
线程抛出各种异常,都别忘了在finally中释放信号量;
如果释放的比获取的信号量还多,例如获取了2个,释放了5次,那么当前信号量就动态的增加为5了,要注意。如下图所示:
例子:用信号量semaphore实现生产者与消费者
请仔细体会里面关于仓库的处理,
1 是如何保证入库时,如果仓库满就等待,
2 出库时,如果仓库无货就等待的。
3 以及对仓库只有10个库位的处理。
4 对同步问题的处理。
- public class TestSemaphore {
- public static void main(String[] args) {
- for (int i = 0; i <= 3; i++) {
- new Thread(new Producer()).start();
- new Thread(new Consumer()).start();
- }
- }
- //仓库
- static WareHouse buffer = new WareHouse();
- //生产者
- static class Producer implements Runnable{
- static int num = 1;
- public void run() {
- int n = num++;
- while(true){
- try{
- buffer.put(n);
- System.out.println(">"+n);
- Thread.sleep(10);
- }catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- static class Consumer implements Runnable{
- public void run() {
- while (true) {
- try {
- System.out.println("<"+buffer.take());
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- static class WareHouse{
- //非满锁
- final Semaphore notFull = new Semaphore(10);
- //非空锁
- final Semaphore notEmpty = new Semaphore(0);
- //互斥锁
- final Semaphore mutex = new Semaphore(1);
- //库存容量
- final Object[] items = new Object[10];
- int putPosi, takePosi, count;
- public void put(Object x)throws InterruptedException{
- try{
- notFull.acquire();
- mutex.acquire();
- items[putPosi] = x;
- if (++putPosi == items.length) {
- putPosi = 0;
- }
- count++;
- }finally{
- notEmpty.release();
- mutex.release();
- }
- }
- public Object take()throws InterruptedException{
- notEmpty.acquire();
- mutex.acquire();
- try{
- Object x = items[takePosi];
- if(++takePosi == items.length){
- takePosi = 0;
- }
- --count;
- return x;
- }finally{
- notFull.release();
- mutex.release();
- }
- }
- }
- }
也可以把Semaphore当锁来使用
当信号量的数量上限是1时,Semaphore可以被当做锁来使用。通过take和release方法来保护关键区域。请看下面的例子:
- BoundedSemaphore semaphore = new BoundedSemaphore(1);
- ...
- semaphore.acquire();
- try{
- //critical section
- } finally {
- semaphore.release();
- }
JAVA多线程之Semaphore的更多相关文章
- Java多线程之Semaphore信号量
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6557874.html 学过操作系统的对 信号量 这个词应该不陌生,它是用来进行进程间通信,控制对 临界区 ...
- Java多线程之ConcurrentSkipListMap深入分析(转)
Java多线程之ConcurrentSkipListMap深入分析 一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...
- JAVA多线程之wait/notify
本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...
- JAVA多线程之volatile 与 synchronized 的比较
一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...
- java多线程之yield,join,wait,sleep的区别
Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...
- Java多线程之Runnable与Thread
Java多线程之Thread与Runnable 一.Thread VS Runnable 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类和 ...
- JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止
JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止 背景 当单线程的程序发生一个未捕获的异常时我们可以采用try....catch进行异常的捕获,但是在多线程环境 ...
- java多线程之wait和notify协作,生产者和消费者
这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...
- Java——多线程之Lock锁
Java多线系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线 ...
随机推荐
- poj 2000 Gold Coins(水题)
一.Description The king pays his loyal knight in gold coins. On the first day of his service, the kni ...
- POJ1703(2集合并查集)
Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 39402 Accepted: ...
- javascript基础之回调函数
简单来说,回调函数:也就是将要执行的函数. 回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A.我们就说函数A叫做回调函数.如果没有名称(函数表达式),就叫 ...
- 异常:Project configuration is not up-to-date with pom.xml解决方案
转自:https://www.cnblogs.com/zhujiabin/p/6343423.html 1. Description Resource Path Location ...
- 【总结整理】javascript的函数调用时是否加括号
javascript的函数调用时是否加括号 if(event.preventDefault){ event.preventDefault(); if判断条件里面不要加括号,不加括号是应该以属性形式,i ...
- CocoaPods常用操作命令
查看镜像: gem sources -l 删除镜像 gem sources --remove https://rubygems.org/ 添加镜像 gem sources -a https://gem ...
- 【eclipse-js验证】
第一步:去除eclipse的JS验证:将windows->preference->Java Script->Validator->Errors/Warnings->Ena ...
- 【C#】VS2017 winform 打包
首先要在想要打包的项目下创建一个新的项目, 创建好setup项目,之后点击属性,去修改打包软件的名字,ProductName....可以选填 到此已经创建好了setup工程了,那么下面开始将要打包的d ...
- sql server 中raiserror的使用
server数据库中raiserror的作用就和asp.net中的throw new Exception一样,用于抛出一个异常或错误.这个错误可以被程序捕捉到. raiserror('错误的描述',错 ...
- 基本图形的绘制(基于skimage)
图形包括线条.圆形.椭圆形.多边形等.在skimage包中,绘制图形用的是draw模块,不要和绘制图像搞混了. 一 线条 函数调用格式: skimage.draw.line(r1,c1,r2 ...