SemaphoreTest

package com.ixhong.base.thread;

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

public class SemaphoreTest {
   public static void main(String[] args) {
      ExecutorService service = Executors.newCachedThreadPool();
      final  Semaphore sp = new Semaphore(3);
      for(int i=0;i<10;i++){
         Runnable runnable = new Runnable(){
               public void run(){
               try {
                  sp.acquire();
               } catch (InterruptedException e1) {
                  e1.printStackTrace();
               }
               System.out.println("线程" + Thread.currentThread().getName() +
                     "进入,当前已有" + (3-sp.availablePermits()) + "个并发");
               try {
                  Thread.sleep((long)(Math.random()*10000));
               } catch (InterruptedException e) {
                  e.printStackTrace();
               }
               System.out.println("线程" + Thread.currentThread().getName() +
                     "即将离开");
               sp.release();
               //下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" + Thread.currentThread().getName() +
                     "已离开,当前已有" + (3-sp.availablePermits()) + "个并发");
            }
         };
         service.execute(runnable);
      }
   }

}

线程pool-1-thread-1进入,当前已有2个并发
线程pool-1-thread-3进入,当前已有3个并发
线程pool-1-thread-2进入,当前已有2个并发
线程pool-1-thread-2即将离开
线程pool-1-thread-2已离开,当前已有2个并发
线程pool-1-thread-4进入,当前已有3个并发
线程pool-1-thread-4即将离开
线程pool-1-thread-4已离开,当前已有2个并发
线程pool-1-thread-5进入,当前已有3个并发
线程pool-1-thread-1即将离开
线程pool-1-thread-1已离开,当前已有2个并发
线程pool-1-thread-6进入,当前已有3个并发
线程pool-1-thread-3即将离开
线程pool-1-thread-3已离开,当前已有2个并发
线程pool-1-thread-7进入,当前已有3个并发
线程pool-1-thread-5即将离开
线程pool-1-thread-5已离开,当前已有3个并发
线程pool-1-thread-8进入,当前已有3个并发
线程pool-1-thread-6即将离开
线程pool-1-thread-6已离开,当前已有2个并发
线程pool-1-thread-9进入,当前已有3个并发
线程pool-1-thread-9即将离开
线程pool-1-thread-9已离开,当前已有2个并发
线程pool-1-thread-10进入,当前已有3个并发
线程pool-1-thread-10即将离开
线程pool-1-thread-10已离开,当前已有2个并发
线程pool-1-thread-7即将离开
线程pool-1-thread-7已离开,当前已有1个并发
线程pool-1-thread-8即将离开
线程pool-1-thread-8已离开,当前已有0个并发

java api中Semaphore(信号量),用于控制有限资源的并发访问。API也非常好理解,不过有几个需要注意的地方:

  1. Semaphore是纯粹的应用级控制“锁”,使用简单的volitale变量作为信号量信息,通过acquire、release、reduce等显式的可以修改此信号量数字。
  2. 它并没有维护任何锁,也不是控制reentrant的,它不会维护信号和thread的关系。
  3. Semaphore的初始值可以为0,甚至可以为负数。对于acquire调用(信号down),它只会比较现在信号值与0的大小关系,如果<=0那么将不能获得授权。
  4. 对于release(信号up),只是简单的对信号值进行原子增加,经过多次的release,信号值可以超过初始的阀值。
  5. 对于Semaphore(0/-N)的场景,有特殊的使用,这种信号控制,在可以acquire之前,必须经过约定的足够多的release之后才可以被使用。

参考:http://stackoverflow.com/questions/1221322/how-does-semaphore-work

时间: 2024-11-01 16:58:21

SemaphoreTest的相关文章

并发工具类(三)控制并发线程数的Semaphore

简介 Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源.很多年以来,我都觉得从字面上很难理解Semaphore所表达的含义,只能把它比作是控制流量的红绿灯,比如XX马路要限制流量,只允许同时有一百辆车在这条路上行使,其他的都必须在路口等待,所以前一百辆车会看到绿灯,可以开进这条马路,后面的车会看到红灯,不能驶入XX马路,但是如果前一百辆中有五辆车已经离开了XX马路,那么后面就允许有5辆车驶入马路,这个例子里说的车就是线程,驶入马路就表

从零开始学.net多线程系列(三)——同步

本文将涉及如下内容 Wait Handles EventWaitHandle Seamphores Mutex Critical Sections Miscellaneous Objects 这篇文章重点说明多个不同的线程之间的同步问题. WaitHandles 首先,我们必须认识到,当你尝试着理解怎么才能使多个线程在一起协调地很好,最关键的问题是怎样排序这些操作.例如,我们有如下的这些问题: 1. 我们需要创建一个订单 2. 我们需要保存订单,但是除非我们获得了订单号,否则我们无法进行保存操作

Semaphore维护当前访问自身的线程个数

可以实现流量控制,同时访问文件的用户数 import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class SemaphoreTest {     public static void main(String[] args) {         ExecutorService service =

java一些常用并发工具示例

最近把<java并发编程实战>-Java Consurrency in Practice 重温了一遍,把书中提到的一些常用工具记录于此: 一.闭锁(门栓)- CountDownLatch 适用场景:多线程测试时,通常为了精确计时,要求所有线程都ready后,才开始执行,防止有线程先起跑,造成不公平,类似的,所有线程执行完,整个程序才算运行完成. /** * 闭锁测试(菩提树下的杨过 http://yjmyzz.cnblogs.com/) * * @throws InterruptedExcep

java之JUC系列-外部Tools-Executors|Semaphor|Exchanger|CyclicBarrier|CountDownLatch

前面写了两篇JDBC源码的文章,自己都觉得有点枯燥,先插一段JUC系列的文章来换换胃口,前面有文章大概介绍过J U C包含的东西,JUC体系包含的内容也是非常的多,不是一两句可以说清楚的,我这首先列出将会列举的JUC相关的内容,然后介绍本文的版本:Tools部分 J.U.C体系的主要大板块包含内容,如下图所示: 注意这个里面每个部分都包含很多的类和处理器,而且是相互包含,相互引用的,相互实现的. 说到J UC其实就是说java的多线程等和锁,前面说过一些状态转换,中断等,我们今天来用它的tool

C#中的线程(二)线程同步

Keywords:C# 线程Source:http://www.albahari.com/threading/Author: Joe AlbahariTranslator: Swanky WuPublished: http://www.cnblogs.com/txw1958/Download:http://www.albahari.info/threading/threading.pdf    第二部分:线程同步基础   同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具: 简易

Java多线程知识小抄集(二)

本文主要整理博主遇到的Java多线程的相关知识点,适合速记,故命名为"小抄集".本文没有特别重点,每一项针对一个多线程知识做一个概要性总结,也有一些会带一点例子,习题方便理解和记忆. 27. ConcurrentHashMap ConcurrentHashMap是线程安全的HashMap,内部采用分段锁来实现,默认初始容量为16,装载因子为0.75f,分段16,每个段的HashEntry<K,V>[]大小为2.键值都不能为null.每次扩容为原来容量的2倍,Concurre

Semaphore的使用

Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制.使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数. Semaphore的主要方法摘要: void acquire()**:**从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断. void release():释放一个许可,将其返回给信号量. int availablePermits():返回此信号量中当前可用的许可数. boolean has

基于Java回顾之多线程同步的使用详解_java

首先阐述什么是同步,不同步有什么问题,然后讨论可以采取哪些措施控制同步,接下来我们会仿照回顾网络通信时那样,构建一个服务器端的"线程池",JDK为我们提供了一个很大的concurrent工具包,最后我们会对里面的内容进行探索. 为什么要线程同步? 说到线程同步,大部分情况下, 我们是在针对"单对象多线程"的情况进行讨论,一般会将其分成两部分,一部分是关于"共享变量",一部分关于"执行步骤". 共享变量 当我们在线程对象(Run