一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
Semaphore构造方法permits参数作用
参数permits的作用是设置许可的个数,当传入大于1的许可,代表同一时间内,主最多允许有X个线程可以执行acquire()和release()之间的代码。
修改SemaphoreService类的许可个数如下:
@Slf4j
public class SemaphoreService {
private Semaphore semaphore = new Semaphore(2);
public void testSemaphore(){
semaphore.acquire();
log.info("线程名:{}-开始执行时间:{}",Thread.currentThread().getName(),System.currentTimeMillis());
Thread.sleep(5000);
log.info("线程名:{}-结束执行时间:{}",Thread.currentThread().getName(),System.currentTimeMillis());
semaphore.release();
}
}
重新执行运行类结果如下:
14:55:49.355 [B] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:B-开始执行时间:1648882549325
14:55:49.350 [A] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:A-开始执行时间:1648882549318
14:55:54.344 [B] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:B-结束执行时间:1648882554344
14:55:54.345 [C] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:C-开始执行时间:1648882554345
14:55:54.417 [A] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:A-结束执行时间:1648882554417
14:55:55.480 [C] INFO com.ozx.concurrentprogram.semaphore.service.SemaphoreService - 线程名:C-结束执行时间:1648882555480
由此可以看出同一时间只有2个线程可以同时执行acquire()和release()之间的代码。
对于SemaphoreService类的构造方法传递的参数permits值大于1时,该类不能保证线程安全性,因为有可能出现多个线程共同访问实例变量,导致出现脏数据的情况。
方法acquire(int permits)参数作用及动态添加permits许可数量
有参方法acquire(int permits)的功能是每调用1次此方法,就使用x个许可。
创建多个许可获取或释放的类代码如下:
@Slf4j
public class SemaphoreService {
private Semaphore semaphore = new Semaphore(10);
public void testSemaphore(){
try {
semaphore.acquire(2);
log.info("线程名:{}-开始执行时间:{}",Thread.currentThread().getName(),System.currentTimeMillis());
int sleepTime = (int)(Math.random() * 10000);
log.info("线程名:{}-休眠时间:{} 秒",Thread.currentThread().getName(),sleepTime/1000);
Thread.sleep((int)Math.random()*1000);
log.info("线程名:{}-结束执行时间:{}",Thread.currentThread().getName(),System.currentTimeMillis());
semaphore.release(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}