zoukankan      html  css  js  c++  java
  • Java信号量Semaphore

    Semaphore

    Semaphore分为单值和多值两种,前者只能被一个线程获得,后者可以被若干个线程获得。

    Semaphore实现的功能就类似厕所有5个坑,假如有10个人要上厕所,那么同时只能有多少个人去上厕所呢?同时只能有5个人能够占用,当5个人中 的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了。另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。

    再以一个停车场运作为例。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。

    在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

    更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait(等待)操作时,它要么通过然后将信号量减一,要么一直等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为加操作实际上是释放了由信号量守护的资源。

    Semaphore(int permits, boolean fair)
    //创建具有给定的许可数和给定的公平设置的Semaphore。

    还可以设置该信号量是否采用公平模式,如果以公平方式执行,则线程将会按到达的顺序(FIFO)执行,如果是非公平,则可以后请求的有可能排在队列的头部。

    使用

    Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

    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 exec = Executors.newCachedThreadPool();
            // 只能5个线程同时访问
            final Semaphore semp = new Semaphore(5);
            // 模拟20个客户端访问
            for (int index = 0; index < 50; index++) {
                final int NO = index;
                Runnable run = new Runnable() {
                    public void run() {
                        try {
                            // 获取许可
                            semp.acquire();
                            System.out.println("Accessing: " + NO);
                            Thread.sleep((long) (Math.random() * 10000));
                            // 访问完后,释放
                            semp.release();
                            //availablePermits()指的是当前信号灯库中有多少个可以被使用
                            System.out.println("-----------------" + semp.availablePermits()); 
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                };
                exec.execute(run);
            }
            // 退出线程池
            exec.shutdown();
        }
    }
    Accessing: 0
    Accessing: 1
    Accessing: 2
    Accessing: 4
    Accessing: 6
    Accessing: 8
    -----------------0
    -----------------1
    Accessing: 3
    -----------------1
    Accessing: 5
    Accessing: 9
    -----------------0
    -----------------1
    Accessing: 7
    Accessing: 10
    -----------------0
    -----------------1
    Accessing: 11
    -----------------1
    Accessing: 12
    -----------------1
    Accessing: 13
    Accessing: 14
    -----------------0
    -----------------1
    Accessing: 15
    -----------------0
    Accessing: 16
    -----------------1
    Accessing: 17
    -----------------1
    Accessing: 18
    -----------------1
    Accessing: 19
    -----------------0
    Accessing: 20
    Accessing: 21
    -----------------0
    Accessing: 22
    -----------------0
    -----------------1
    Accessing: 23
    -----------------1
    Accessing: 24
    -----------------0
    Accessing: 25
    Accessing: 26
    -----------------0
    -----------------1
    Accessing: 27
    -----------------1
    Accessing: 28
    -----------------1
    Accessing: 29
    Accessing: 30
    -----------------0
    -----------------1
    Accessing: 31
    -----------------1
    Accessing: 32
    -----------------1
    Accessing: 33
    -----------------1
    Accessing: 34
    Accessing: 35
    -----------------0
    -----------------1
    Accessing: 36
    -----------------1
    Accessing: 37
    -----------------1
    Accessing: 38
    -----------------1
    Accessing: 39
    -----------------1
    Accessing: 40
    Accessing: 41
    -----------------0
    -----------------1
    Accessing: 42
    Accessing: 43
    -----------------0
    Accessing: 44
    -----------------0
    -----------------1
    Accessing: 45
    -----------------1
    Accessing: 46
    -----------------1
    Accessing: 47
    -----------------1
    Accessing: 48
    -----------------1
    Accessing: 49
    -----------------1
    -----------------2
    -----------------3
    -----------------4
    -----------------5

    我是天王盖地虎的分割线

    参考:http://www.cnblogs.com/linjiqin/archive/2013/07/25/3214676.html

  • 相关阅读:
    DataAnnotations
    使用BizTalk实现RosettaNet B2B So Easy
    biztalk rosettanet 自定义 pip code
    Debatching(Splitting) XML Message in Orchestration using DefaultPipeline
    Modifying namespace in XML document programmatically
    IIS各个版本中你需要知道的那些事儿
    关于IHttpModule的相关知识总结
    开发设计的一些思想总结
    《ASP.NET SignalR系列》第五课 在MVC中使用SignalR
    《ASP.NET SignalR系列》第四课 SignalR自托管(不用IIS)
  • 原文地址:https://www.cnblogs.com/yydcdut/p/4300361.html
Copyright © 2011-2022 走看看