一起养成写作习惯!这是我参与「掘金日新计划 · 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许可个数。