Java中信号量Semaphore的使用以及和线程池的区别

Java架构师交流群:793825326

java版本:jdk1.8

IDE:Idea2019

Semaphore属于Java并发库里面的类,它在我看来算是线程池的一种吧,当然它和真正的线程池还是有些差别的。它的原理是管理一定数量的许可证,当线程要运行的时候,首先从它这里获取许可证(acquire),如果它的许可证发放完了,那么这个线程就要等待,直到其他的线程释放了许可证(release)。参考如下的示例代码:

private static final Semaphore semaphore=new Semaphore(2);
    public static void main(String[] args) {

        Thread thread1=new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    semaphore.acquire();
                    System.out.println("thread1 start");
                    for (int i = 0; i < 10; i++) {
                        Thread.sleep(500);
                        System.out.println("thread1 is working");
                    }
                    System.out.println("thread1 end");
                    semaphore.release();
                } catch (Exception ex) {
                    System.out.println(ex.toString());
                }
            }
        });

        Thread thread2=new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    semaphore.acquire();
                    System.out.println("thread2 start");
                    for (int i = 0; i < 5; i++) {
                        Thread.sleep(500);
                        System.out.println("thread2 is working");
                    }
                    System.out.println("thread2 end");
                    semaphore.release();
                } catch (Exception ex) {
                    System.out.println(ex.toString());
                }
            }
        });

        Thread thread3=new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    semaphore.acquire();
                    System.out.println("thread3 start");
                    System.out.println("thread3 end");
                    semaphore.release();
                } catch (Exception ex) {
                    System.out.println(ex.toString());
                }
            }
        });
        try {
            thread1.start();
            thread2.start();
            thread3.start();
        }
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
}

这段代码的执行结果为:

thread1 start
thread2 start
thread1 is working
thread2 is working
thread1 is working
thread2 is working
thread2 is working
thread1 is working
thread1 is working
thread2 is working
thread2 is working
thread2 end
thread1 is working
thread3 start
thread3 end
thread1 is working
thread1 is working
thread1 is working
thread1 is working
thread1 is working
thread1 end

thread3尝试获取许可证失败,因为许可证只有两个,只能等待,直到thread2释放了许可证,thread3才往下执行。

下面简单说一下信号量和线程池的区别。

它们之间的区别有两点:

1)线程池是会开启新线程,而信号量不开启新线程,信号量所谓的新线程是使用者自己开启的。

2)线程池等到线程结束后会自动释放许可,信号量的许可不管是获取还是释放,都需要手动操作。

这就决定了它俩的使用场景上的不同,线程池的使用场景,不用多说,就是管理线程,避免线程滥用。信号量的使用场景,我认为更多的是避免一些代码同时运行太多,比如有个方法,可能会在很多线程里面使用,但是我们又不想让这个方法在太多线程里面同时调用,因为可能会耗费大量的系统资源,这个时候,你就可以增加一个全局的信号量,让这个方法在执行前获取许可,执行结束后释放许可,这样就避免了太多地方同时执行这个方法。在高并发的应用场景中,我们可能经常会有限流的操作,就是让接口同时接受的请求数量有一个上限,达到上限,其他的就要等待,这里就可以用信号量来解决。还有,假如有两个方法A和B,我们不希望这两个方法同时被执行,在同一时间,只允许一个方法被执行,那么我们仍然可以用信号量来解决。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值