juc(三):semaphore如何做访问控制

1.案例分析:

(1)100个线程运行一段程序,要求同时只能有10个线程运行
(2) 抢车位:有3个停车位,但是有6个车需要停,模拟抢夺过程

2.代码实现:

(1)需求1代码实现

package com.example.test;
import java.util.Random;
import java.util.concurrent.Semaphore;

public class semaphore {
        private final static Semaphore MAX_SEMA_PHORE = new Semaphore(10);
        public static void main(String []args) {
            for(int i = 0 ; i < 100 ; i++) {
                final int num = i;
                final Random radom = new Random();
                new Thread() {
                    public void run() {
                        boolean acquired = false;
                        try {
                            MAX_SEMA_PHORE.acquire();
                            acquired = true;
                            System.out.println("我是线程:" + num + " 我获得了使用权!" );
                            long time = 1000 * Math.max(1, Math.abs(radom.nextInt() % 10));
                            Thread.sleep(time);
                            System.out.println("我是线程:" + num + " 我执行完了!" );
                        }catch(Exception e) {
                            e.printStackTrace();
                        }finally {
                            if(acquired) {
                                MAX_SEMA_PHORE.release();
                            }
                        }
                    }
                }.start();
            }
        }
    }

运行结果:
在这里插入图片描述
(2)需求2 代码实现:

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
    /**
     * 模拟抢车位:6辆车,抢3个车位
     */
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3); //模拟3个车位
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                try {
                    //强到车位
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"\t抢到了车位");
                    //模拟停车3s
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread().getName()+"\t停车3s后离开车位");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    //停了3s后离开车位
                    semaphore.release();
                }
            },String.valueOf(i)).start();
        }
    }
}

3.代码解读:
发现没有,上述控制资源所采用的方法是信号量,semaphore,当线程运行一段时间后,会释放信号,然后就有新的线程进入,线程数始终维持在我们设定的数量值。 信号量可以理解为对锁的扩展,无论是内部锁synchronized还是重入锁ReentrantLock,一次只允许一个线程访问一个资源,而信号量却可以指定多个线程,同时访问同一个资源。

Semaphore提供的构造器

public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}
//参数permits:许可数目,即同时可以允许多少线程进行访问//参数fair:是否是公平的,即等待时间越久的越先获取许可
public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}

Semaphore中比较重要的方法

//获得一个许可public void acquire() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);}
//获取permits个许可public void acquire(int permits) throws InterruptedException {
    if (permits < 0) throw new IllegalArgumentException();
    sync.acquireSharedInterruptibly(permits);}
//释放一个许可public void release() {
    sync.releaseShared(1);}
//释放permits个许可public void release(int permits) {
    if (permits < 0) throw new IllegalArgumentException();
    sync.releaseShared(permits);}
//尝试获取一个许可,若获取成功,则立即返回true,若获取失败,则立即返回falsepublic boolean tryAcquire() {
    return sync.nonfairTryAcquireShared(1) >= 0;}
//尝试获取permits个许可,若获取成功,则立即返回true,若获取失败,则立即返回falsepublic boolean tryAcquire(int permits) {
    if (permits < 0) throw new IllegalArgumentException();
    return sync.nonfairTryAcquireShared(permits) >= 0;}
//尝试获取一个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回falsepublic boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException {
    return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}
//尝试获取permits个许可,若在指定的时间内获取成功,则立即返回true,否则则立即返回falsepublic boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException {
    if (permits < 0) throw new IllegalArgumentException();
    return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值