`
sealbird
  • 浏览: 584065 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

老紫竹JAVA提高教程-信号量(Semaphore)在生产者和消费者模式的使用

    博客分类:
  • JAVA
阅读更多
Semaphore 信号量,就是一个允许实现设置好的令牌。也许有1个,也许有10个或更多。
谁拿到令牌(acquire)就可以去执行了,如果没有令牌则需要等待。
执行完毕,一定要归还(release)令牌,否则令牌会被很快用光,别的线程就无法获得令牌而执行下去了。

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

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

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

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

4 对同步问题的处理。

view plaincopy to clipboardprint?
01.import java.util.concurrent.Semaphore;   
02./**  
03. * 老紫竹JAVA提高教程-信号量(Semaphore)的使用。<br>  
04. * 生产者和消费者的例子,库存的管理。  
05. *   
06. * @author 老紫竹(java2000.net,laozizhu.com)  
07. */  
08.public class TestSemaphore {   
09.  public static void main(String[] args) {   
10.    // 启动线程   
11.    for (int i = 0; i <= 3; i++) {   
12.      // 生产者   
13.      new Thread(new Producer()).start();   
14.      // 消费者   
15.      new Thread(new Consumer()).start();   
16.    }   
17.  }   
18.  // 仓库   
19.  static Warehouse buffer = new Warehouse();   
20.  // 生产者,负责增加   
21.  static class Producer implements Runnable {   
22.    static int num = 1;   
23.    @Override  
24.    public void run() {   
25.      int n = num++;   
26.      while (true) {   
27.        try {   
28.          buffer.put(n);   
29.          System.out.println(">" + n);   
30.          // 速度较快。休息10毫秒   
31.          Thread.sleep(10);   
32.        } catch (InterruptedException e) {   
33.          e.printStackTrace();   
34.        }   
35.      }   
36.    }   
37.  }   
38.  // 消费者,负责减少   
39.  static class Consumer implements Runnable {   
40.    @Override  
41.    public void run() {   
42.      while (true) {   
43.        try {   
44.          System.out.println("<" + buffer.take());   
45.          // 速度较慢,休息1000毫秒   
46.          Thread.sleep(1000);   
47.        } catch (InterruptedException e) {   
48.          e.printStackTrace();   
49.        }   
50.      }   
51.    }   
52.  }   
53.  /**  
54.   * 仓库  
55.   *   
56.   * @author 老紫竹(laozizhu.com)  
57.   */  
58.  static class Warehouse {   
59.    // 非满锁   
60.    final Semaphore notFull = new Semaphore(10);   
61.    // 非空锁   
62.    final Semaphore notEmpty = new Semaphore(0);   
63.    // 核心锁   
64.    final Semaphore mutex = new Semaphore(1);   
65.    // 库存容量   
66.    final Object[] items = new Object[10];   
67.    int putptr, takeptr, count;   
68.    /**  
69.     * 把商品放入仓库.<br>  
70.     *   
71.     * @param x  
72.     * @throws InterruptedException  
73.     */  
74.    public void put(Object x) throws InterruptedException {   
75.      // 保证非满   
76.      notFull.acquire();   
77.      // 保证不冲突   
78.      mutex.acquire();   
79.      try {   
80.        // 增加库存   
81.        items[putptr] = x;   
82.        if (++putptr == items.length)   
83.          putptr = 0;   
84.        ++count;   
85.      } finally {   
86.        // 退出核心区   
87.        mutex.release();   
88.        // 增加非空信号量,允许获取商品   
89.        notEmpty.release();   
90.      }   
91.    }   
92.    /**  
93.     * 从仓库获取商品  
94.     *   
95.     * @return  
96.     * @throws InterruptedException  
97.     */  
98.    public Object take() throws InterruptedException {   
99.      // 保证非空   
100.      notEmpty.acquire();   
101.      // 核心区   
102.      mutex.acquire();   
103.      try {   
104.        // 减少库存   
105.        Object x = items[takeptr];   
106.        if (++takeptr == items.length)   
107.          takeptr = 0;   
108.        --count;   
109.        return x;   
110.      } finally {   
111.        // 退出核心区   
112.        mutex.release();   
113.        // 增加非满的信号量,允许加入商品   
114.        notFull.release();   
115.      }   
116.    }   
117.  }   
118.}  
import java.util.concurrent.Semaphore;
/**
 * 老紫竹JAVA提高教程-信号量(Semaphore)的使用。<br>
 * 生产者和消费者的例子,库存的管理。
 * 
 * @author 老紫竹(java2000.net,laozizhu.com)
 */
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;
    @Override
    public void run() {
      int n = num++;
      while (true) {
        try {
          buffer.put(n);
          System.out.println(">" + n);
          // 速度较快。休息10毫秒
          Thread.sleep(10);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
  // 消费者,负责减少
  static class Consumer implements Runnable {
    @Override
    public void run() {
      while (true) {
        try {
          System.out.println("<" + buffer.take());
          // 速度较慢,休息1000毫秒
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
  /**
   * 仓库
   * 
   * @author 老紫竹(laozizhu.com)
   */
  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 putptr, takeptr, count;
    /**
     * 把商品放入仓库.<br>
     * 
     * @param x
     * @throws InterruptedException
     */
    public void put(Object x) throws InterruptedException {
      // 保证非满
      notFull.acquire();
      // 保证不冲突
      mutex.acquire();
      try {
        // 增加库存
        items[putptr] = x;
        if (++putptr == items.length)
          putptr = 0;
        ++count;
      } finally {
        // 退出核心区
        mutex.release();
        // 增加非空信号量,允许获取商品
        notEmpty.release();
      }
    }
    /**
     * 从仓库获取商品
     * 
     * @return
     * @throws InterruptedException
     */
    public Object take() throws InterruptedException {
      // 保证非空
      notEmpty.acquire();
      // 核心区
      mutex.acquire();
      try {
        // 减少库存
        Object x = items[takeptr];
        if (++takeptr == items.length)
          takeptr = 0;
        --count;
        return x;
      } finally {
        // 退出核心区
        mutex.release();
        // 增加非满的信号量,允许加入商品
        notFull.release();
      }
    }
  }
}

发表于 @ 2009年03月17日 11:11:00 | 评论( 4 ) | 编辑| 举报| 收藏

旧一篇:平庸和优秀的距离,我要得不仅仅是土豆 | 新一篇:国内顶级IT公司面试题的答案
查看最新精华文章 请访问博客首页相关文章
生产者消费者问题的java实现有趣的生产者消费者问题老紫竹JAVA提高教程(1)-认识Set集合老紫竹JAVA提高教程(7)-认识List列表之ArrayListQt 多线程学习(1)线程同步Condition Variables JAVA多线程生产者消费者问题——Java方案zhangweiheb 发表于2009年3月17日 22:06:26  IP:举报回复删除
今天上午的操作系统的课也讲到这里了,本来也想用Java写个例子试一下,看来赵老师先把样板写出来了,哈哈...
顺便问一下赵老师,Semaphore 和 synchronize 有什么联系吗?liu251 发表于2010年1月7日 18:49:25  IP:举报回复删除
在有些系统中没有互斥锁mutex原语,只有信号量,此时synchronized的实现是通过semaphore实现的yin_slin 发表于2010年7月23日 17:20:54  IP:举报回复删除
代码很精彩,写出了Semaphore的用途,特别是核心锁的互斥作用,但这段代码性能并不高,生产者和消费者是单线程运作的,没有体现concurrency包的高性能特性

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/java2000_net/archive/2009/03/17/3997449.aspx
分享到:
评论

相关推荐

    JAVA多线程--信号量(Semaphore)_.docx

    在Java中,还可以设置该信号量是否采纳公正模式,假如以公正方式执行,则线程将会按到达的挨次(FIFO)执行,假如是非公正,则可以后恳求的有可能排在队列的头部。 JDK中定义如下: ``` Semaphore(int permits, ...

    使用信号量(Semaphore)实现线程的同步

    通过信号量,可以确保缓冲区不满时生产者才能生产,缓冲区不空时消费者才能消费。 - **读者-写者问题**:多个读者可以同时读取数据,但写入时需要独占资源。使用信号量,可以实现多个读者同时读取,而写入时阻塞所有...

    使用信号量实现有限缓冲区的生产者和消费者问题

    总结来说,使用信号量实现有限缓冲区的生产者和消费者问题以及读进程具有优先权的读者和写者问题,关键在于正确地设计和操作信号量,确保并发进程的正确同步和互斥。在Linux下,C语言提供了丰富的接口支持信号量的...

    用多线程同步方法解决生产者-消费者问题(操作系统课设

    2. 信号量的实现:我们使用信号量来控制生产者和消费者的访问顺序。 3. 生产者线程的实现:我们实现了生产者线程的逻辑,包括生产数据和释放缓冲区的空闲信号量。 4. 消费者线程的实现:我们实现了消费者线程的逻辑...

    生产者消费者实验报告.doc

    在这个实验中,通过Java的并发库(如`ReentrantLock`或`Semaphore`)实现信号量机制,确保生产者不会在缓冲区满时生产产品,消费者也不会在缓冲区空时尝试消费。实验的实施有助于深入理解操作系统中并发控制和资源...

    Java线程间的通信----生产者消费者模型

    生产者消费者模型是一种经典的线程同步问题,它模拟了实际生活中的生产过程和消费过程,使得生产者线程可以将数据生产出来,而消费者线程则负责消耗这些数据,两者之间通过共享数据结构进行协同工作。 生产者消费者...

    多线程简易实现生产者消费者模式

    总之,生产者消费者模式是多线程编程中的一种重要设计模式,它通过信号量和条件变量实现了线程间的同步和通信,有效提高了系统资源的利用率和整体效率。在Java中,我们可以借助并发库轻松实现这一模式,使得代码更加...

    System V共享内存与信号量综合应用之生产者与消费者问题解决

    在生产者-消费者问题中,我们可以使用两个信号量:一个用于保护缓冲区的满/空状态(例如,设为buffer_size),另一个用于控制缓冲区中的产品数量(例如,设为count)。当缓冲区满时,生产者会阻塞直到count信号量有...

    java生产者消费者demo

    在生产者消费者问题中,适配器模式可能被用来协调生产者和消费者之间的通信,确保数据的正确生产和消费。 在Java中,有几种常见的解决生产者消费者问题的方法: 1. **阻塞队列(BlockingQueue)**:Java并发包`...

    java 编写的生产者与消费者问题

    这个库提供了多种工具类,如Semaphore(信号量)、BlockingQueue(阻塞队列)和Condition(条件变量),这些都可以用来实现生产者-消费者模型。 1. **BlockingQueue**: 阻塞队列是一种特殊的队列,它具有线程安全的...

    界面话模拟生产者消费者模式java

    在"界面话模拟生产者消费者模式java"的项目中,开发者创建了一个用户界面,允许用户自定义生产者生产数据的数量、消费者消费数据的数量,以及仓库(缓冲区)的最大容量、最小剩余量,还有生产者每次生产的数据量和...

    进程同步模拟设计--生产者和消费者问题

    总结来说,进程同步模拟设计——生产者和消费者问题是一个典型的多线程同步问题,通过使用信号量等同步机制,我们可以实现并发进程间的有效协作,保证数据的一致性和系统的正常运行。在实际编程中,理解并熟练运用...

    java 多线程 生产者消费者模式

    生产者消费者模式还有其他变体,比如使用信号量(Semaphore)或条件变量(Condition)来控制生产者和消费者的数量或行为。例如,你可以限制同时运行的消费者数量,或者在特定条件下唤醒某个线程。 此外,`java.util...

    Swift-dispatch-semaphore

    在iOS开发中,理解并熟练使用`DispatchSemaphore`对于优化代码性能和处理同步问题至关重要。本文将深入探讨`DispatchSemaphore`的原理、用法以及在实际开发中的应用场景。 `DispatchSemaphore`是一种信号量机制,它...

    Java多线程 生产者-消费者模式

    Java多线程中的生产者-消费者模式是一种典型的同步与协作模型,它用于解决在多线程环境下资源的有效利用和协调问题。在这个模式中,通常有两个角色:生产者和消费者。生产者负责创建产品,而消费者则负责消费这些...

    labview 生产者消费者例子

    在生产者-消费者模型中,可以设置一个信号量来控制队列的满和空状态,限制生产者的生产速率和消费者的消费速率。 7. **例程分析**:在提供的"生产者消费者"例程中,可能包含了创建生产者和消费者线程、初始化队列、...

    JAVA实现线程间同步与互斥生产者消费者问题

    在这个例子中,生产者和消费者可能会使用共享的数据结构(如队列)来存储和获取产品,synchronized关键字将确保在任何时候只有一个线程能执行添加或移除产品的操作。 2. **wait()和notify()方法**:这些方法位于`...

    多进程同步-生产者消费者模式-C实现

    生产者消费者模式基于操作系统提供的信号量(Semaphore)或管程(Monitor)等机制,以解决进程间的通信和同步问题。在这个模式中,生产者进程负责生成数据并放入缓冲区,而消费者进程则负责从缓冲区取出数据进行处理...

    生产者与消费者的实验

    4. **信号量**:在某些实现中,可以使用信号量(Semaphore)来控制对共享资源的访问。在Java中,`java.util.concurrent.Semaphore`类可以创建一个计数信号量,用于限制同时访问特定资源的线程数量。 5. **死锁**:...

    iOS GCD中级篇 - dispatch_semaphore(信号量)的理解及使用1

    以下是一个简单的例子,展示了如何使用信号量来控制同时执行的任务数量。在这个例子中,我们创建了一个信号量,初始值为2,然后启动了3个并发任务。每个任务在执行前都会调用`dispatch_semaphore_wait`获取信号量,...

Global site tag (gtag.js) - Google Analytics