• 静思
  • 吴言片语
    • 吴言
    • 片语
    • 杂七杂八
  • 死于青春
    • 一路走好
  • 乌合麒麟
  • 纪念
    • 5.12
    • 3.23
  • GitHub
    • A List of Post-mortems
    • The Art of Command Line
  • 关于
    • Privacy Policy

程序员的信仰

金鳞岂是池中物,一遇风云便化龙

HOME » 技术生活 » Java Concurrent框架之阻塞队列(Blocking queue)

Java Concurrent框架之阻塞队列(Blocking queue)

2005 年 10 月 11 日 @ 下午 4:56 by Jay | 被踩了 2,324 脚

引子:
大家上过操作系统的都知道“生产者-消费者(Producer-Consumer)”模型,主要讨论的是进程(线程)间的互斥和同步问题,关键是对锁(lock)的申请、独占和释放,在这里我就不罗嗦了。原先我写的Java代码如下:

public class Producer extends Thread{
  private ProductList products = ProductList.getInstance();
  
  public void run(){
    int i = 0;
    
    while(i <= 20){
      synchronized(products){ // Get lock on product list
        if(products.isFull()){
          System.out.println("List is full");
          products.notify(); // Release the lock
        } else{
          Product product = new Product(i++); // Produce a product
          products.put(product);
          System.out.println("Produced product " + product.getId());
          products.notify(); // Release lock
        }
      } // Release the lock
    }
  }
}

public class Consumer extends Thread{
  ProductList products = ProductList.getInstance();
  
  public void run(){
    while(true){
      synchronized(products){
        try {
          products.wait(); // Wait for lock
          Product product = null;
          if(!(products.isEmpty()))
            product = products.take();
          else
            System.out.println("List is empty");
          System.out.println("Consumed product " + product.getId()); // Get the lock
        } catch (InterruptedException ex) {
          ex.printStackTrace();
        }
      } // Release the lock
    }
  }
}
import java.util.ArrayList;
import java.util.List;

public class ProductList {
  private static ProductList instance = new ProductList();
  private List products; // Adapter pattern
  public static final int SIZE = 10;
  
  private ProductList() {
    products = new ArrayList(SIZE);
  }
  
  public static ProductList getInstance() { // Singleton pattern
    return instance;
  }
  
  public boolean isFull() {
    return products.size() == SIZE;
  }
  
  public void put(Product product) {
    products.add(product);
  }
  
  public Product take() {
    return products.remove(0);
  }
  
  public boolean isEmpty() {
    return products.isEmpty();
  }
}

public class Product {
  private int id;
  
  public Product(int id) {
    this.id = id;
  }
  
  public int getId() {
    return id;
  }
}

public class Main {
  public static void main(String[] args){
    Producer p = new Producer();
    Consumer c = new Consumer();
    
    p.start();
    c.start();
  }
}

虽然Java对信号量及原语做了更高层次的封装(wait()、notify()、notifyAll()、synchronized{}),但看完上述代码还是觉得有点麻烦,于是JDK 5在原先collection框架的基础上增加了java.util.concurrent包,封装了许多用于线程并发操作的数据结构和操作。其中的BlockingQueue接口就是封装了一个阻塞队列的接口,具体地说就是实现了一个用于消费者(多个)和生产者(多个)交换产品的中介,生产者线程在队列满时阻塞,消费者线程在队列空时阻塞,当然在没有得到锁之前两类线程均会阻塞。详细信息可以参考Java Doc。下面用BlockingQueue实现P-C模型:

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while(true) { queue.put(produce()); }
     } catch (InterruptedException ex) {  handle }
   }
   Object produce() {  }
}

class Consumer implements Runnable {
  private final BlockingQueue queue;
  Consumer(BlockingQueue q) { queue = q; }
  public void run() {
    try {
      while(true) { consume(queue.take()); }
    } catch (InterruptedException ex) {  handle }
  }
  void consume(Object x) {  }
}

class Setup {
  void main() {
    BlockingQueue q = new SomeQueueImplementation();
    Producer p = new Producer(q);
    Consumer c1 = new Consumer(q);
    Consumer c2 = new Consumer(q);
    new Thread(p).start();
    new Thread(c1).start();
    new Thread(c2).start();
  }
}

可以看出代码中没有出现wait()或notify()之类的原语操作,这些操作由concurrent框架负责封装。更全面的讨论可以参考《驯服 Tiger: 并发集合》(IBM)


-- EOF --

除非注明(如“转载”、“[zz]”等),本博文章皆为原创内容,转载时请注明: 「转载自程序员的信仰©」
本文链接地址:Java Concurrent框架之阻塞队列(Blocking queue)

分享

  • 点击分享到 Facebook (在新窗口中打开) Facebook
  • 点击以分享到 X(在新窗口中打开) X
  • 更多
  • 点击分享到Reddit(在新窗口中打开) Reddit
  • 点击分享到Telegram(在新窗口中打开) Telegram
  • 点击以在 Mastodon 上共享(在新窗口中打开) Mastodon

赞过:

赞 正在加载……

相关

Posted in: 技术生活 Tagged: collection, concurrent, ibm, java, tiger
← Object Modeling Strategies (IV)
Google Earth(上海市延安中学(高中),详尽标注版) →

android (9) apple (20) augmentum (9) Beijing (21) bt (8) career (28) coding (38) firefox (10) google (36) hibernate (11) ibm (11) iphone (10) java (93) linux (16) m$ (26) mac (58) macos (27) nazca (9) olympics (8) oo (8) playstation (10) rip (8) Shanghai (39) spring (9) tips (45) tommy emmanuel (8) ubuntu (12) usa (23) windows (9) 北航 (17) 博客 (29) 吐槽 (8) 周末 (9) 和谐社会 (26) 小资 (11) 愤青 (40) 方言 (10) 朋友 (77) 歌词 (8) 烟酒不分家 (18) 爱国 (19) 爱情 (8) 犯二 (15) 破解 (8) 足球 (11)

烫手山芋

  • 再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~ - 被踩了 27,444 脚
  • 生活,就是一个期待跟着一个期待 - 被踩了 21,359 脚
  • 星巴克饮品缩写大全(Starbucks Drink ID Codes)[zz] - 被踩了 18,417 脚
  • 从一个全角冒号说一下我为什么不感冒iOS - 被踩了 14,333 脚
  • 有关Character.isLetter()和Character.isLetterOrDigit() - 被踩了 13,591 脚

刚拍的砖

  • leo 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》
  • 花 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》
  • 无名氏 发表在《从一个全角冒号说一下我为什么不感冒iOS》
  • Jay 发表在《Mac OS geek级问题》
  • Wei Wang 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》

随便看看

  • 冬奥金牌九宫格,GET4 年 ago
  • 晚上和老七去北大看Tommy的演奏会,了强子的心愿…16 年 ago
  • 夺金时刻!中国队38金海报合集来了![zz]4 年 ago
  • 时寒冰:剖析楼市真相与趋势 [zz]9 年 ago
  • IBM i Is Modern. Windows and UNIX Are Legacy.14 年 ago

文以类聚

光阴似箭

其他操作

  • 登录
  • 条目 feed
  • 评论 feed
  • WordPress.org

Copyright © 2025 程序员的信仰.

Jay's Omega WordPress Theme by Jay

 

正在加载评论...
 

    %d