疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java信号量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