现在有一个需求,方法A和方法B首先不能同时运行,是互斥的,但是方法A是慢服务,只允许同时一个线程调用方法,而方法B效率就挺高的,允许5个线程同时访问方法,要实现这样的条件,才能最大化效率。
这时使用信号量来完成这个需求就是一个很好的选择
public class SpringbootApplication {
final static Semaphore semaphore = new Semaphore(5);
final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static class A implements Runnable {
@Override
public void run() {
try {
semaphore.acquire(5);
System.out.println(sdf.format(new Date()) + ":" + "A服务" + Thread.currentThread().getName() + "获取许可证");
//假设处理业务逻辑要3秒
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(sdf.format(new Date()) + ":" + "A服务" + Thread.currentThread().getName() + "释放许可证");
semaphore.release(5);
}
}
}
static class B implements Runnable {
@Override
public void run() {
try {
semaphore.acquire(1);
System.out.println(sdf.format(new Date()) + ":" + "B服务" + Thread.currentThread().getName() + "获取许可证");
//假设处理业务逻辑要1秒
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(sdf.format(new Date()) + ":" + "B服务" + Thread.currentThread().getName() + "释放许可证");
semaphore.release(1);
}
}
}
public static void main(String[] args) throws Exception {
//假设有个线程访问了A方法
new Thread(new A()).start();
//假设有5个线程访问了B方法
for (int i = 0; i < 5; i++) {
new Thread(new B()).start();
}
//假设有个线程访问了A方法
new Thread(new A()).start();
}
运行结果:
以上截图这是运行结果之一,多线程的运行结果是很多变的,除非做了同步,不过还是可以很清晰的看到,A方法和B方法实现了互斥,以及B方法允许最多5个线程同时访问的效果。
总结
通过上述例子,只是分享一个思路,我们在开发中,完全可以根据业务的需求来合理利用信号量,以此达到想要的资源分配效果。