【并发编程】- Semaphore-acquireUninterruptibly()使用

483 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

​ 如果多次调用SemaphoreService类的release()或release(int)方法时,还可以动态增加permits的个数。

使用release()方法动态增加permits个数代码如下:

@Slf4j
public class TestSemaphorePermits {

    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore = new Semaphore(5);
        semaphore.acquire();
        semaphore.acquire();
        semaphore.acquire();
        semaphore.acquire();
        semaphore.acquire();
        log.info("剩余的许可个数:{}",semaphore.availablePermits());
        semaphore.release();
        semaphore.release();
        semaphore.release();
        semaphore.release();
        semaphore.release();
        semaphore.release();
        semaphore.release();
        log.info("剩余的许可个数:{}",semaphore.availablePermits());
        semaphore.release(3);
        log.info("剩余的许可个数:{}",semaphore.availablePermits());
    }
}

执行运行类结果如下:

15:48:18.880 [main] INFO com.ozx.concurrentprogram.semaphore.controller.TestSemaphorePermits - 剩余的许可个数:0
15:48:18.889 [main] INFO com.ozx.concurrentprogram.semaphore.controller.TestSemaphorePermits - 剩余的许可个数:7
15:48:18.889 [main] INFO com.ozx.concurrentprogram.semaphore.controller.TestSemaphorePermits - 剩余的许可个数:10

注意点:

构造函数new Semaphore(5)中的数值并不是最终的许可数量,只是定义初始的状态值。

方法acquireUninterruptibly()的使用

方法acquireUninterruptibly()的作用是使等待进入acquire()方法的线程,不允许被中断。

直接使用acquire()方法,运行类触发异常

@Slf4j
public class SemaphoreService {
    private Semaphore semaphore = new Semaphore(1);

    public void testSemaphore(){
        try {
            semaphore.acquire();
            log.info("线程名:{}-开始执行时间:{}",Thread.currentThread().getName(),System.currentTimeMillis());
            for (int i = 0; i < Integer.MAX_VALUE/50; i++) {
                String msg = new String();
                Math.random();
            }
            log.info("线程名:{}-结束执行时间:{}",Thread.currentThread().getName(),System.currentTimeMillis());
            semaphore.release();
        } catch (InterruptedException e) {
            log.error("线程名:{} 进入了catch",Thread.currentThread().getName());
            e.printStackTrace();
        }
    }
}

运行类代码如下:

@Slf4j
public class TestAcquireUninterruptibly {

    public static void main(String[] args) throws InterruptedException {
        SemaphoreService service = new SemaphoreService();
        ThreadA threadA = new ThreadA(service);
        threadA.setName("A");
        ThreadB threadB = new ThreadB(service);
        threadB.setName("B");
        ThreadC threadC = new ThreadC(service);
        threadC.setName("C");
        threadA.start();
        threadB.start();
        threadC.start();

        Thread.sleep(1000);
        threadB.interrupt();
     }
}

程序运行结果如下:

11:26:38.442 [A] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:A-开始执行时间:1649215598415
11:26:39.414 [B] ERROR com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:B 进入了catch
java.lang.InterruptedException
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:998)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
	at java.util.concurrent.Semaphore.acquire(Semaphore.java:312)
	at com.ozx.concurrentprogram.semaphore.service.SemaphoreService.testSemaphore(SemaphoreService.java:19)
	at com.ozx.concurrentprogram.semaphore.entity.ThreadB.run(ThreadB.java:21)
11:26:41.033 [A] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:A-结束执行时间:1649215601033
11:26:41.034 [C] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:C-开始执行时间:1649215601034
11:26:43.064 [C] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:C-结束执行时间:1649215603064

若不想获取许可被中断,使用acquireUninterruptibly()方法替换acquire()方法。

acquireUninterruptibly()方法还有重载的写法acquireUninterruptibly(int permits),此方法的作用是在等待许可的情况下不允许被中断,如果成功获取锁,则取得指定的permits许可个数。