java访问并发控制semaphore使用与总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/d597180714/article/details/79961161

semaphore 这个类是用作访问并发控制,可以设置资源最大同时访问的个数。
初始化时参数1 permits(许可数),定义资源可以并发访问的最大个数
例如

public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(3);//资源最多可被3个线程并发访问
        for(int i = 0;i < 20;i++){
            final int threadnum = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("current thread"+Thread.currentThread().getName());
                        semaphore.acquire(1);//获取许可
                        test(threadnum);
                        semaphore.release(1);//释放许可
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executorService.shutdown();//如果不shutdown工程不会结束
    }

    private static void test(int threadNum) throws Exception {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        System.out.println(simpleDateFormat.format(new Date())+"  method run "+Thread.currentThread().getName());
        Thread.sleep(1000);
    }

核心方法semaphore.acquire()默认一次获取一个许可,也可以一次获取多个许可,例如semaphore.acquire(3),如果当前可获取的许可数不足,那么当前线程被阻塞。CPU调度其他线程执行。当可以获取到许可时,线程继续执行,当访问需要的资源结束时需要调用semaphore.release(),默认释放一个许可,也可以释放多个许可。如果忘记释放许可,那么当初始化定义的所有许可都被使用完后,其他线程获取不到许可都会处于阻塞状态,程序就无法继续运行。该段代码中我们对test()方法进行了访问并发控制,最大允许3个线程访问执行该方法。
运行结果如下:
这里写图片描述
可以看到test()方法确实每次只有3个线程能执行,其他的都处于阻塞状态。
Semaphore还可以定义是否公平
fair为TRUE时先阻塞的先获得锁
源码实现:

public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}

semaphore.tryAcquire();尝试获取一个锁,成功返回TRUE失败返回false
代码:

public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(3);//资源最多可被3个线程并发访问
        for(int i = 0;i < 10;i++){
            final int threadnum = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName()+" running");
                      if(semaphore.tryAcquire()){
                          test(threadnum);
                          semaphore.release(1);
                      }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executorService.shutdown();//如果不shutdown工程不会结束
    }

    private static void test(int threadNum) throws Exception {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        System.out.println(simpleDateFormat.format(new Date())+"  method run "+Thread.currentThread().getName());
        Thread.sleep(1000);
    }

运行结果:
这里写图片描述
只有3个线程执行了test()方法,其他尝试获取锁失败的线程就丢弃了
还有带参数的tryAcquire方法,第一个参数是等待的时间,第二个是等待时间的单位。
带参数时,方法会在定义的时间内一直尝试获取许可。
semaphore.tryAcquire(2,TimeUnit.SECONDS)

阅读更多

没有更多推荐了,返回首页