zoukankan      html  css  js  c++  java
  • JAVA多线程之Semaphore

    Semaphore:动态增减信号量,用于控制对某资源访问的同一时间的并发量。类似于令牌,谁拿到令牌(acquire)就可以去执行了,如果没有令牌则需要等待。

    【如何获取】:
    semaphore.tryAcquire(),尝试获取,不阻塞。

    semaphore.acquire(),没信号量可用时,将进行阻塞等,可以被中断。

    acquireUninterruptibly():获取信号量,将进行阻塞,会忽略线程的中断而且不会抛出任何异常。

    【如何释放】:
    semaphore.release();
    线程抛出各种异常,都别忘了在finally中释放信号量;
    如果释放的比获取的信号量还多,例如获取了2个,释放了5次,那么当前信号量就动态的增加为5了,要注意。如下图所示:

    例子:用信号量semaphore实现生产者与消费者

    请仔细体会里面关于仓库的处理,

    1 是如何保证入库时,如果仓库满就等待,

    2 出库时,如果仓库无货就等待的。

    3 以及对仓库只有10个库位的处理。

    4 对同步问题的处理。

    public class TestSemaphore {
        public static void main(String[] args) {
            for (int i = 0; i <= 3; i++) {
                new Thread(new Producer()).start();
                new Thread(new Consumer()).start();
            }
        }
        //仓库  
        static WareHouse buffer = new WareHouse();  
        //生产者
        static class Producer implements Runnable{
            static int num = 1;
            public void run() {
                int n = num++;
                while(true){
                    try{
                        buffer.put(n);
                        System.out.println(">"+n);
                        Thread.sleep(10);
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        static class Consumer implements Runnable{
            public void run() {
                while (true) {
                    try {
                        System.out.println("<"+buffer.take());
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        static class WareHouse{
            //非满锁
            final Semaphore notFull = new Semaphore(10);
            //非空锁
            final Semaphore notEmpty = new Semaphore(0);
            //互斥锁
            final Semaphore mutex = new Semaphore(1);
            //库存容量
            final Object[] items = new Object[10];
            int putPosi, takePosi, count;
            public void put(Object x)throws InterruptedException{
                try{
                    notFull.acquire();
                    mutex.acquire();
                    items[putPosi] = x;
                    if (++putPosi == items.length) {
                        putPosi = 0;
                    }
                    count++;
                }finally{
                    notEmpty.release();
                    mutex.release();
                }
            }
            public Object take()throws InterruptedException{
                notEmpty.acquire();
                mutex.acquire();
                try{
                    Object x = items[takePosi];
                    if(++takePosi == items.length){
                        takePosi = 0;
                    }
                    --count;
                    return x;
                }finally{
                    notFull.release();
                    mutex.release();
                }
            }
        }
    }

     也可以把Semaphore当锁来使用

    当信号量的数量上限是1时,Semaphore可以被当做锁来使用。通过take和release方法来保护关键区域。请看下面的例子:

    BoundedSemaphore semaphore = new BoundedSemaphore(1);
    ...
    semaphore.acquire();
    try{
      //critical section
    } finally {
      semaphore.release();
    }
  • 相关阅读:
    MVC3、如何应用EntityFramework 连接MySql 数据库 Kevin
    DEV EXPRESS Summary Footer 不显示 Kevin
    装饰模式 Kevin
    Dev 控件 GridControl 控件 二次绑定数据源的问题。 Kevin
    System.InvalidOperationException 异常 Kevin
    LINQ to XML Kevin
    代理模式——代码版“吊丝的故事” Kevin
    VS2012 中的设备 面板 Kevin
    maven 学习笔记(三)创建一个较复杂的 eclipse+android+maven 工程
    maven 学习笔记(一)eclipse+android+maven
  • 原文地址:https://www.cnblogs.com/pingh/p/3502760.html
Copyright © 2011-2022 走看看