信号量Semaphore的使用

一、概念

Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。

一个信号量有且仅有3种操作,且它们全部是原子的:初始化、增加和减少 
增加可以为一个进程解除阻塞; 
减少可以让一个进程进入阻塞。

和线程池的区别:使用Seamphore,创建了多少线程,实际就会有多少线程进行执行,只是可同时执行的线程数量会受到限制。但使用线程池,不管你创建多少线程,实际可执行的线程数是一定的。

二、方法

1 构造方法:

Semaphore(int)、Semaphore(int,boolean)

int表示该信号量拥有的许可数量

boolean表示获取许可的时候是否是公平的。(公平指的是先来的先执行)

2 获取许可

acquire()、acquire(int)、tryAcquire()

int参数表示一次性要获取几个许可,默认为1个,acquire方法在没有许可的情况下,要获取许可的线程会阻塞。

tryAcquire()方法在没有许可的情况下会立即返回 false,要获取许可的线程不会阻塞。

3 释放许可

release()、release(int)

int参数表示一次性要释放几个许可,默认为1个,

注意一个线程调用release()之前并不要求一定要调用了acquire因此如果释放的比获取的信号量还多,例如获取了2个,释放了5次,那么当前信号量就动态的增加为5了(实现动态增加)

4 当前可用的许可数

int availablePermits()

三、测试

public void testSemaphore()
{
    // 线程池
    ExecutorService exec = Executors.newCachedThreadPool();
    // 只能5个线程同时访问
    final Semaphore semp = new Semaphore(2);
    // 模拟20个客户端访问
    for (int index = 0; index < 5; index++) {
        final int NO = index;
        Runnable run = new Runnable() {
            @Override
            public void run() {
                try {
                    if (semp.availablePermits() > 0) {
                        System.out.println( NO + "线程启动");
                    else {
                        System.out.println(NO + "线程启动,排队等待");
                    }
                    // 获取许可
                    semp.acquire();
                    System.out.println(NO + "线程执行" );
                    //模拟实际业务逻辑
                    Thread.sleep((long) (Math.random() * 10000));
                    // 访问完后,释放
                    semp.release();
                    System.out.println(NO + "线程释放");
                catch (InterruptedException e) {
                }
            }
        };
        exec.execute(run);
    }
 
    try {
        Thread.sleep(10);
    catch (InterruptedException e) {
        e.printStackTrace();
    }
 
    //System.out.println(semp.getQueueLength());
 
 
 
    // 退出线程池
    exec.shutdown();
}

0线程启动
0线程执行
1线程启动
1线程执行
2线程启动,排队等待
3线程启动,排队等待
4线程启动,排队等待
2线程执行
0线程释放
1线程释放
3线程执行
2线程释放
4线程执行
3线程释放
4线程释放

 
原文地址:https://www.cnblogs.com/aiguona/p/10634045.html