分类: Java技术

     锁和信号量(Semaphore)是实现多线程同步的两种常用的手段。信号量需要初始化一个许可值,许可值可以大于0,也可以小于0,也可以等于0.

     如果大于0,表示,还有许可证可以发放,线程不会被阻塞;
     如果小于或者等于0,表示,没有许可证可以发放了,线程被阻塞住了。
     它有两个常用的操作,acquire()申请许可证,如果有,就可以获得,如果没有就等待了。
                         release(),归还许可证,保证循环使用。

     看一个例子,就会明白了,还是实现上次的那个生产者和消费者的例子。
     我们假设有一个篮子,最多可以放3个苹果,有多个人可以放苹果,也有多个人可以拿走苹果。
public class Apple {
    private String name;
    public Apple(String name){
       this. name= name;
    }
        @Override
        public String toString() {
               // TODO Auto-generated method stub
               return name ;
       }

}

public class Basket {
        private List bascket =new ArrayList(10);
       Semaphore mutex = new Semaphore(1);
       Semaphore isFull = new Semaphore(10);
       
       Semaphore isEmpty = new Semaphore(0);
       
        public void put(Apple app) throws InterruptedException{
               //大于0,就放行
               //acquire,就是减操作,如果小于0,就阻塞
               //release,就是加操作,如果大于0,就不会被阻塞
               isFull. acquire();
               try{
                      mutex. acquire();
                  bascket.add( app);
              }
               finally{
                      mutex.release();
                      isEmpty.release();
              }
       }
       
        public Apple take() throws InterruptedException{
              Apple app;
               isEmpty. acquire();
               try{
                      mutex. acquire();
                      app= bascket.remove(0);
              }
               finally{
                      mutex.release();
                      isFull.release();
              }
               return app ;
       }

}

//消费者
public class Consumer implements Runnable{
        private Basket bascket ;
        private String name ;
        public Consumer(Basket bascket ,String name ){
               this .bascket =bascket ;
               this .name =name ;
       }
        public void run(){
               while (true ){
                      try {
                           System. out .println(name +":consumer" +bascket .take());
                     } catch (InterruptedException e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                     }
                      try {
                           Thread. sleep(1000);
                     } catch (InterruptedException e ) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                     }
              }
       }

}

//生产者
public class Producer implements Runnable{
        private Basket bascket ;
        private String name ;
        public Producer(Basket bascket ,String name ){
               this .bascket =bascket ;
               this .name =name ;
       }
        public void run(){
              
               while (true ){
                      try {
                           System. out .println(name +"produce.." );
                            bascket. put( new Apple( "name" +new Random()));
                     } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                     }
                      try {
                           Thread. sleep(1000);
                     } catch (InterruptedException e ) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                     }
                     
              }
              
       }

}

public class TestDemo {
        public static void main(String args[]){
              Basket bascket= new Basket();
              Consumer c1= new Consumer(bascket ,"c1" );
              
              Producer p1= new Producer(bascket ,"p1" );
              Producer p2= new Producer(bascket ,"p2" );
              
               //线程池管理
              ExecutorService service = Executors. newCachedThreadPool();
               service.execute( c1);
               service.execute( p1);
               service.execute( p2);
       }
}

一定要注意,上面acquire的顺序,如果不正确,所有的线程就会被阻塞了。
信号量的实现原理会在源代码中进行分析。

JAVA并发框架之Semaphore实现生产者与消费者模型的更多相关文章

  1. Java并发框架AbstractQueuedSynchronizer(AQS)

    1.前言 本文介绍一下Java并发框架AQS,这是大神Doug Lea在JDK5的时候设计的一个抽象类,主要用于并发方面,功能强大.在新增的并发包中,很多工具类都能看到这个的影子,比如:CountDo ...

  2. 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.AQS框架简介 AQS诞生于Jdk1.5,在当时低效且功能单一的synchroni ...

  3. 深入理解Java并发框架AQS系列(四):共享锁(Shared Lock)

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock) 深入 ...

  4. Java 并发系列之十:java 并发框架(2个)

    1. Fork/Join框架 2. Executor框架 3. ThreadPoolExecutor 4. ScheduledThreadPoolExecutor 5. FutureTask 6. t ...

  5. 深入理解Java并发框架AQS系列(一):线程

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.概述 1.1.前言 重剑无锋,大巧不工 读j.u.c包下的源码,永远无法绕开的经典 ...

  6. 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型

    关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...

  7. python并发编程之守护进程、互斥锁以及生产者和消费者模型

    一.守护进程 主进程创建守护进程 守护进程其实就是'子进程' 一.守护进程内无法在开启子进程,否则会报错二.进程之间代码是相互独立的,主进程代码运行完毕,守护进程也会随机结束 守护进程简单实例: fr ...

  8. 生产者和消费者模型producer and consumer(单线程下实现高并发)

    #1.生产者和消费者模型producer and consumer modelimport timedef producer(): ret = [] for i in range(2): time.s ...

  9. Python 之并发编程之进程下(事件(Event())、队列(Queue)、生产者与消费者模型、JoinableQueue)

    八:事件(Event()) # 阻塞事件:    e = Event() 生成事件对象e    e.wait() 动态给程序加阻塞,程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值 ...

随机推荐

  1. Windows Store App JavaScript 开发:选取文件和文件夹

    前面提到过,文件打开选取器由FileOpenPicker类表示,用于选取或打开文件,而文件夹选取器由FolderPicker类表示,用来选取文件夹.在FileOpenPicker类中,pickSing ...

  2. WEBSTORM 2016.3 activation code激活

    选择activation code 激活方式,复制粘贴下面的激活码43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoi ...

  3. 作业调度框架 Quartz 学习笔记(三) -- Cron表达式 (转载)

    前面两篇说的是简单的触发器(SimpleTrigger) , SimpleTrigger 只能处理简单的事件出发,如果想灵活的进行任务的触发,就要请出 CronTrigger 这个重要人物了. Cro ...

  4. Jquery做点击选中与鼠标移上特效

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. repcache实现memcached主从

    1.repcached介绍 repcached是日本人开发的实现memcached复制功能,它是一个单 master单 slave的方案,但它的 master/slave都是可读写的,而且可以相互同步 ...

  6. java解析XML文件

    dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点,同时它也是一个开放源 ...

  7. 前端工程师IE6兼容性问题随笔(未完待续)

    1 height.在IE6下元素高度小于19px的时候,会被当做19px来处理.解决办法:用overflow:hidden;来处理.box{height:2px;background:red;over ...

  8. <java基础学习>RE 基础语法(2)

    Java Modifiers(java修饰符): Like other languages, it is possible to modify classes, methods, etc., by u ...

  9. C++ 类、构造析构、深拷贝

    1st,感性理解类的思想,就是把数据和对数据的操作打包在一块儿,设计类的时候要 想好数据部分和 要进行的操作.以下是时间类的示意,时间包含时分秒,Time为构造函数,该类支持的操作就是设置时间和读取时 ...

  10. NSOperation的start与main,并发与非并发。

    http://blog.csdn.net/a2331046/article/details/52294006 在ios4以前,只有非并发的情况下,队列会为operation开启一个线程来执行.如果是并 ...