Java多线程编程核心技术——生产者消费者模型
2017-02-28 10:46
239 查看
生产者消费者模型是并发中的经典问题,具体场景是有一块缓冲区作为仓库,生产者可以向其添加产品,消费者可以从中取出产品。解决生产者消费者问题可以采用两种方式:wait()/notify方式和BlockingQueue方式,在此主要讨论第一种,关于第二种方法可以参考Ranger的Audit模型。
wait()/notify()是Object的两个方法,也是并发中常见的两个方法:wait会使线程阻塞,直到一个notify通知其继续执行。下面通过一段代码来说明这两个方法。
MyThread提供了list作为产品仓库,produce和consume方法模拟生产产品和消费产品的过程。值得注意的是,因为list涉及多个线程对其操作,不管是生产还是消费,都需要对list加锁,防止出现“脏读”。当list中产品过剩时,需要暂停生产者的produce过程,直到消费者消费掉一定的产品,使仓库能有足够的空间容纳新产品并向生产者发送通知生产者才可以继续生产;同样,当仓库空了,需要暂停消费者的consume过程,直到生产者生产了产品之后向消费者发送通知,消费者才可以继续消费。此处的暂停/通知就是通过wait()/notify()方法实现的。
wait()与notify()都必须在同步块中使用,wait()使线程等待,notify()则会通知线程继续运行,需要注意的是,如果有多个处在wait状态的线程,一个notify会随机的通知其中一个线程继续运行,其它线程仍旧处于wait状态。而notifyAll()方法会通知所有处于wait状态的线程继续运行,但是因为wait处于同步代码块中,接到通知只是会让线程退出wait状态,至于能否真正的继续运行还要看线程能否抢到同步锁。
wait()/notify()是Object的两个方法,也是并发中常见的两个方法:wait会使线程阻塞,直到一个notify通知其继续执行。下面通过一段代码来说明这两个方法。
public class MyThread implements Runnable { private String name; private List<String> list = new ArrayList<String>(); private final int size = 10; public void produce(int num) throws Exception { while (true) { synchronized (list) { while (list.size() + num > size) { System.out.println(Thread.currentThread().getName()+"生产过剩,等待消费"); list.wait(); } System.out.println(Thread.currentThread().getName()+"正在生产"); for (int i = 0; i < num; i++) { list.add("hello, world"); } list.notify(); } Thread.sleep(1000); } } public void consume() throws Exception { while (true) { synchronized (list) { while (list.size() == 0) { System.out.println(Thread.currentThread().getName()+"已无产品可消费,等待生产"); list.wait(); } System.out.println(Thread.currentThread().getName()+"正在消费"); list.remove(0); list.notify(); } Thread.sleep(1000); } } public void setName(String name) { this.name = name; } public void run() { try { if ("producer".equals(name)) { produce(1); } else { consume(); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { try { MyThread myThread = new MyThread(); myThread.setName("producer"); Thread t1 = new Thread(myThread); Thread t4 = new Thread(myThread); t1.start(); t4.start(); Thread.sleep(1); myThread.setName("consumer"); Thread t2 = new Thread(myThread); Thread t3 = new Thread(myThread); t2.start(); t3.start(); } catch (Exception e) { } } }
MyThread提供了list作为产品仓库,produce和consume方法模拟生产产品和消费产品的过程。值得注意的是,因为list涉及多个线程对其操作,不管是生产还是消费,都需要对list加锁,防止出现“脏读”。当list中产品过剩时,需要暂停生产者的produce过程,直到消费者消费掉一定的产品,使仓库能有足够的空间容纳新产品并向生产者发送通知生产者才可以继续生产;同样,当仓库空了,需要暂停消费者的consume过程,直到生产者生产了产品之后向消费者发送通知,消费者才可以继续消费。此处的暂停/通知就是通过wait()/notify()方法实现的。
wait()与notify()都必须在同步块中使用,wait()使线程等待,notify()则会通知线程继续运行,需要注意的是,如果有多个处在wait状态的线程,一个notify会随机的通知其中一个线程继续运行,其它线程仍旧处于wait状态。而notifyAll()方法会通知所有处于wait状态的线程继续运行,但是因为wait处于同步代码块中,接到通知只是会让线程退出wait状态,至于能否真正的继续运行还要看线程能否抢到同步锁。
相关文章推荐
- Java 技术: 使您轻松地进行多线程应用程序编程——Consumer 类可以简化生产者-消费者行为的实现
- 【Java 多线程】简单生产者消费者模型
- 生产者消费者模型的四种java编程例子
- java技术深入(一)——java多线程(七)——阻塞队列,生产者-消费者模式
- JAVA实现多线程生产者消费者模型
- 【Java并发编程】之十三:生产者—消费者模型(含代码)
- java多线程生产者、消费者模型
- Java多线程-并发协作(生产者消费者模型)
- java多线程并发协作:生产者消费者模型
- 从Java多线程实现“生产者-消费者”模型来谈谈操作系统中线程状态的转换
- Java实践之路——多线程之生产者消费者模型
- java多线程交互 经典实例__生产者与消费者模型
- Java多线程之~~~~使用wait和notify实现生产者消费者模型
- java 多线程之 wait(),notify(),notifyAll()以及经典的生产者消费者模型
- Java多线程-并发协作(生产者消费者模型)
- Java多线程-并发协作(生产者消费者模型)
- 【Java并发编程】之十三:生产者—消费者模型(含代码)
- 【Java并发编程】之十三:生产者—消费者模型(含代码)
- Java多线程-并发协作(生产者消费者模型)
- Java多线程 -- 生产者消费者模型