一 Samaphore的概念和工作流程
1 概念
信号量;它允许线程集等待,直到被允许继续运行为止,一个信号量管理多个许可,线程必须请求许可,否则等待。
特点:控制访问多个共享资源的计数器。
使用场景:通常用于限制访问资源的线程总数,流量控制。
基本操作:acquire(); 获取一个许可
release(); 释放一个许可
二 基本使用
使用场景:一个停车场可以停放10两小汽车或者5辆大卡车(一辆大卡车占用2个小汽车的停车位),现有14辆小汽车,8辆大卡车要进入停车场。
示例代码
package com.bxp.threadtest.samaphoretest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreTest {
static Logger logger = LoggerFactory.getLogger(SemaphoreTest.class);
/**
* 默认使用非公平锁
*/
private static Semaphore semaphore = new Semaphore(10);
public static void main(String[] args) {
Car car = new Car();
Truck truck = new Truck();
for (int i = 0; i < 14; i++) {
new Thread(car).start();
}
for (int i = 0; i < 8; i++) {
new Thread(truck).start();
}
}
public static class Car implements Runnable{
@Override
public void run() {
try {
semaphore.acquire();
logger.info("小汽车" + Thread.currentThread().getName() + "进入停车场");
Random random = new Random();
int time = random.nextInt(20);
TimeUnit.SECONDS.sleep(time);
logger.error("小汽车" + Thread.currentThread().getName() + "停留" + time + "秒");
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
semaphore.release();
}
}
}
public static class Truck implements Runnable{
@Override
public void run() {
try {
semaphore.acquire(2);
logger.info("大卡车" + Thread.currentThread().getName() + "进入停车场");
Random random = new Random();
int time = random.nextInt(20);
TimeUnit.SECONDS.sleep(time);
logger.error("大卡车" + Thread.currentThread().getName() + "停留" + time + "秒");
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
semaphore.release(2);
}
}
}
}
运行结果:
23:12:31.295 [Thread-3] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-3进入停车场
23:12:31.295 [Thread-4] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-4进入停车场
23:12:31.295 [Thread-9] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-9进入停车场
23:12:31.295 [Thread-6] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-6进入停车场
23:12:31.296 [Thread-11] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-11进入停车场
23:12:31.296 [Thread-1] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-1进入停车场
23:12:31.295 [Thread-2] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-2进入停车场
23:12:31.295 [Thread-0] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-0进入停车场
23:12:31.296 [Thread-5] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-5进入停车场
23:12:31.295 [Thread-8] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-8进入停车场
23:12:31.322 [Thread-2] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-2停留0秒
23:12:31.322 [Thread-4] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-4停留0秒
23:12:31.322 [Thread-7] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-7进入停车场
23:12:31.322 [Thread-10] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-10进入停车场
23:12:32.327 [Thread-7] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-7停留1秒
23:12:33.308 [Thread-11] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-11停留2秒
23:12:33.310 [Thread-18] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-18进入停车场
23:12:34.307 [Thread-1] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-1停留3秒
23:12:40.310 [Thread-6] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-6停留9秒
23:12:40.310 [Thread-0] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-0停留9秒
23:12:40.311 [Thread-17] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-17进入停车场
23:12:41.315 [Thread-8] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-8停留10秒
23:12:41.316 [Thread-16] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-16进入停车场
23:12:42.301 [Thread-3] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-3停留11秒
23:12:42.301 [Thread-13] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-13进入停车场
23:12:44.310 [Thread-9] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-9停留13秒
23:12:44.310 [Thread-12] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-12进入停车场
23:12:44.325 [Thread-10] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-10停留13秒
23:12:45.315 [Thread-12] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-12停留1秒
23:12:45.315 [Thread-14] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-14进入停车场
23:12:47.314 [Thread-13] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-13停留5秒
23:12:49.313 [Thread-18] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-18停留16秒
23:12:49.314 [Thread-19] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-19进入停车场
23:12:50.304 [Thread-5] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 小汽车Thread-5停留19秒
23:12:50.304 [Thread-15] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-15进入停车场
23:12:52.306 [Thread-15] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-15停留2秒
23:12:52.306 [Thread-20] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-20进入停车场
23:12:52.322 [Thread-19] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-19停留3秒
23:12:52.322 [Thread-16] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-16停留11秒
23:12:52.322 [Thread-21] INFO com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-21进入停车场
23:12:53.319 [Thread-17] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-17停留13秒
23:12:57.327 [Thread-14] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-14停留12秒
23:13:04.332 [Thread-21] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-21停留12秒
23:13:11.314 [Thread-20] ERROR com.bxp.threadtest.samaphoretest.SemaphoreTest - 大卡车Thread-20停留19秒
三 注意事项
1 注意事项
(1)Samaphore默认使用的是非公平锁,可以在创建时指定使用公平锁。
(2)线程可以申请多个许可,也可以释放多个许可。
acquire(n); 获取n个许可
release(n); 释放n个许可
(3)许可数量初始化为1时,可以当做普通的互斥锁来使用。
(4)获取许可和释放许可的是线程,不是semaphore对象