java Semaphore(信号量)

1.信号量用来累计唤醒的次数,从而不会产生notify信号丢失的问题。信号量也要指定初始信号的大小,acquire()方法将信号量的值减一,如果信号量的值小于等于零,那么调用线程会阻塞。而release()方法将信号量加一,并且不会产生阻塞。关键:信号量的取值,判断,修改以及可能发生的阻塞这一系列操作都是原子操作。

2.信号量可以用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量,还可以用来实现某种资源池,或者对容器加边界。使用初始信号为1的信号量可以实现互斥锁。

3.信号量的acquire()默认从等待池中随机选择一个阻塞的线程,并且是可闯入的,即刚好有一个资源并且有一个线程刚好调用acquire(),那么它有能获得资源而不是优先选择在等待池中的线程。
但是在初始化信号量时可以设置参数fairness为true,这样选择线程时将采用FIFO的顺序并且不可闯入。

4.例子:
1.实现生产者消费者问题

public class SemaphoreExample {
    private int size; // 存放产品的槽的数目
    private int[] array;// 存放产品的容器
    private Semaphore mutex;// 互斥量,控制每次只能有一个线程访问数组,也可以用synchronized
    private Semaphore empty; // 记录空槽数目
    private Semaphore full; // 记录满槽数目
    private Random rand;

    public SemaphoreExample(int size) {
        this.size = 0;
        empty = new Semaphore(size);
        full = new Semaphore(0);
        mutex = new Semaphore(1);
        rand = new Random();
        array = new int[size];
    }

    public void prodecter() throws InterruptedException {
        int item = rand.nextInt(100);
        // 获得添加元素的许可
        empty.acquire();
        // 获得访问数组的许可
        mutex.acquire();
        array[size++] = item;
        System.out.println("add " + item);
        // 立即释放互斥锁
        mutex.release();
        // 添加元素后,增加许可
        full.release();
    }

    public void constomer() throws InterruptedException {
        // 获得取出元素的许可
        full.acquire();
        // 获得访问数组的许可
        mutex.acquire();
        System.out.println("get " + array[--size]);
        // 立即释放锁
        mutex.release();
        // 取出元素后,增加许可
        empty.release();
    }

    public static void main(String[] args) throws InterruptedException {
        SemaphoreExample obj = new SemaphoreExample(5);
        CountDownLatch start = new CountDownLatch(1);
        CountDownLatch canStart = new CountDownLatch(10);
        // 五个生产者线程
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                public void run() {
                    try {
                        canStart.countDown();
                        // 等待开关开始
                        start.await();
                        obj.prodecter();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            }).start();
        }

        // 五个消费者线程
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                public void run() {
                    try {
                        canStart.countDown();
                        // 等待开关开始
                        start.await();
                        obj.constomer();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            }).start();
        }
        //等待10个线程都开始运行
        canStart.await();
        start.countDown();
    }
}
result:
add 27
add 34
get 34
add 67
get 67
add 71
get 71
add 78
get 78
get 27
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值