JAVA并发包-同步工具(3)---Semaphore信号量

package com.day20180312;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;


/**
 * 我们以一个停车场运作为例来说明信号量的作用。假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦。
 * 以后来的车必须在入口等待,直到停车场中有车辆离开。这时,如果有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开一辆,则又可以放入一辆,如此往复。

       在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
        信号量是一个非负整数,表示了当前公共资源的可用数目(在上面的例子中可以用空闲的停车位类比信号量),当一个线程要使用公共资源时(在上面的例子中可以用车辆类比线程),
        首先要查看信号量,如果信号量的值大于1,则将其减1,然后去占有公共资源。
        如果信号量的值为0,则线程会将自己阻塞,直到有其它线程释放公共资源。


 * 在创建Semaphore对象的时候还可以指定它的公平性。
 * 一般常用非公平的信号量,非公平信号量是指在获取许可时先尝试获取许可,而不必关心是否已有需要获取许可的线程位于等待队列中,如果获取失败,才会入列。
 * 而公平的信号量在获取许可时首先要查看等待队列中是否已有线程,如果有则入列。
 * 
 * 在信号量上我们定义两种操作: acquire(获取) 和 release(释放)。
 * 当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等下去,直到有线程释放信号量,或超时。
 * release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。


       信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制。


 * 构造函数源代码


//非公平的构造函数
public Semaphore(int permits) {
   sync = new NonfairSync(permits);
}

//通过fair参数决定公平性
public Semaphore(int permits, boolean fair) {
   sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}


 * @author jeff
 * 2018年6月2日
 */
public class TestSemaphore {
//参数permits表示许可数:3
private Semaphore smp = new Semaphore(3); 
//随机数
private Random rnd = new Random();

//任务线程
class TaskDemo implements Runnable{

private String id;

TaskDemo(String id){
this.id = id;
}

@Override
public void run(){
try {
smp.acquire();//获取信号量 --》获取成功,则许可数减1,如果许可数为0则获取失败,线程阻塞,进入AQS等待队列中,它会被其它释放许可的线程唤醒
System.out.println("Thread " + id + " is working");//成功获取信号量 打印工作线程Id
Thread.sleep(rnd.nextInt(1000));
smp.release();//释放信号量,许可数加1
System.out.println("Thread " + id + " is over");
} catch (InterruptedException e) {
}
}
}

/**
* 创建多个任务:
* 可以看出,最多同时有三个线程并发执行,也可以认为有三个公共资源
* @param args
*/
public static void main(String[] args){
TestSemaphore semaphoreDemo = new TestSemaphore();
//注意我创建的线程池类型,
ExecutorService se = Executors.newCachedThreadPool();
se.submit(semaphoreDemo.new TaskDemo("a"));
se.submit(semaphoreDemo.new TaskDemo("b"));
se.submit(semaphoreDemo.new TaskDemo("c"));
se.submit(semaphoreDemo.new TaskDemo("d"));
se.submit(semaphoreDemo.new TaskDemo("e"));
se.submit(semaphoreDemo.new TaskDemo("f"));
se.shutdown();
}
}

猜你喜欢

转载自blog.csdn.net/shengqianfeng/article/details/80551397