生产者与消费者之间加入一个“桥梁参与者”,它用来缓冲两者之间的处理速度。
示例:MakerThread用来不断的产生cake,把cake送到table上;而EaterThread不断的eat cake。Table用来缓冲两者的生产消费过程,put方法中如果出现table满了,那么put方法就要等待,table不满了就被notify了,然后把cake放到table上,并notify那些EaterThread;take方法发现table空了,那么一直等到有cake(被notify的时候当然有cake咯),然后吃掉一个。
import java.util.Random; public class MakerThread extends Thread{ private final Random random; private final Table table; private static int id=0;//蛋糕的流水线号码 public MakerThread(String name,Table table,long seed){ super(name); this.table=table; this.random=new Random(seed); } public void run(){ try{ while(true){ Thread.sleep(random.nextInt(1000)); String cake="[cake No."+nextId()+" by "+getName()+"]"; table.put(cake); } }catch(InterruptedException e){ e.printStackTrace(); } } private static synchronized int nextId() { return id++; } }
import java.util.Random; public class EaterThread extends Thread { private final Random random; private final Table table; public EaterThread(String name,Table table,long seed){ super(name); this.table=table; this.random=new Random(seed); } public void run(){ try{ while(true){ table.take(); Thread.sleep(random.nextInt(1000)); } }catch(InterruptedException e){ e.printStackTrace(); } } }
public class Table { private final String[] buffer; private int tail; //下一个put的地方 private int head; //下一个take的地方 private int count; public Table(int count){ this.buffer=new String[count]; this.head=0; this.tail=0; this.count=0; } public synchronized void put(String cake) throws InterruptedException{ System.out.println(Thread.currentThread().getName()+" put "+cake); while(count>=buffer.length){ wait(); } buffer[tail]=cake; tail=(tail+1)%buffer.length; count++; notifyAll(); } public synchronized String take() throws InterruptedException{ while(count<=0){ wait(); } String cake=buffer[head]; head=(head+1)%buffer.length; count--; notifyAll(); System.out.println(Thread.currentThread().getName()+" takes "+cake); return cake; } }
public class Main { public static void main(String[] args){ Table table=new Table(3); new MakerThread("Maker1",table,31415).start(); new MakerThread("Maker2",table,92653).start(); new MakerThread("Maker3",table,58979).start(); new EaterThread("Eater1",table,32384).start(); new EaterThread("Eater2",table,62643).start(); new EaterThread("Eater3",table,38327).start(); } }
运行结果:
Maker2 put [cake No.0 by Maker2]
Eater3 takes [cake No.0 by Maker2]
Maker1 put [cake No.1 by Maker1]
Eater1 takes [cake No.1 by Maker1]
Maker3 put [cake No.2 by Maker3]
Eater2 takes [cake No.2 by Maker3]
Maker2 put [cake No.3 by Maker2]
Eater3 takes [cake No.3 by Maker2]
Maker3 put [cake No.4 by Maker3]
线程为了协调合作,所以必须进行共享互斥,使得共享的东西不被损坏。而线程的共享互斥,也是为了让线程合作才进行的。这个模式中的中间参与者就是协调线程运行的关键部分。
关于几个耗时的操作:
1、sleep。执行sleep的线程会暂停执行参数内设置的时间。线程Alice执行Thread.sleep(604800000),然后就一直暂停到给定的时间,如果要取消,那么可以在线程Bobby中执行alice.interrupted();这里alice是线程Alice对应的Thread实例。当sleep的线程调用interrupt方法时,就会放弃暂停状态并且抛出InterruptedException异常。这样一来,线程Alice的控制权就交给捕获这个异常的catch块了。
2、wait。调用wait方法线程会进入等待区,等待的时候线程不会活动,它会直到被notify或notifyAll。
同样可以用interrupt来取消wait,线程Bobby调用alice.interrupted,同样,也会抛出InterruptedException。但要小心锁定的问题,线程进入等待区会把锁定解除,在wait状态下调用interrupt会重新获取锁定,然后再抛出异常。
3、join。执行join方法会等待到指定的线程结束为止。也就是会花费掉指定线程结束这段时间。和sleep方法一样,调用interrupt方法后,由于join方法不需要获得锁定,它会马上跳到catch块里面。
interrupt方法只是改变中断的状态而已。isInterrupted方法可以检查中断状态,如果为中断状态那么返回true,而非中断返回false。Thread.interruted方法可以检查并且清除中断状态,线程会被设置成非中断状态。
相关推荐
用Java实现23种设计模式 1. 创建型模式 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) ... 生产者消费者模式(Producer Consumer Pattern)
ProducerConsumerPattern pattern = new ProducerConsumerPattern(); Thread producer = new Thread(() -> pattern.produce()); Thread consumer = new Thread(() -> pattern.consume()); producer.start(); ...
在LabVIEW编程环境中,"生产者消费者模式"(Producer Consumer Pattern)是一种常用的设计模式,用于处理并发和数据处理流程。这个模式主要用于管理共享资源,确保数据的有序处理,避免数据竞争和死锁问题。在本案例...
生产者-消费者模式(Producer-Consumer pattern)是多线程编程中的一个经典设计模式,用于解决资源共享问题。这个模式的核心思想是通过共享一个缓冲区来实现生产者和消费者之间的协作。在这个模式中,生产者负责生成...
- **生产者-消费者模式(Producer-Consumer Pattern)**:通过队列来解耦生产者和消费者之间的数据交换过程。 - **工作池模式(Worker Pool Pattern)**:预先创建一组线程来执行任务,从而减少线程创建和销毁的成本...
4. **消费者(Consumer)**:从监视者对象中获取并处理数据的线程。 **应用示例** 清单6展示了`Message_Queue`类,其中`get()`和`empty()`、`full()`等方法都是`synchronized`的,意味着它们都持有监视锁。这样...
在IT领域,生产者-消费者模型(Producer-Consumer Pattern)是一种经典的多线程问题解决方案,主要应用于并发编程中。这个模型描述了两个角色——生产者和消费者,它们共享一个有限的资源池,生产者负责创建资源,而...
根据提供的信息,我们可以深入探讨Java经典编程中的一个关键概念——生产者消费者模式(Producer-Consumer Pattern)。这个模式在多线程编程中极为常见,并且是理解并发控制的基础之一。 ### 生产者消费者模式简介 ...
Python在程序并行化方面多少有些声名狼藉。撇开技术上的问题,例如线程的实现和GIL,我...Standard Producer/Consumer Threading Pattern ''' import time import threading import Queue class Consumer(threading.
- **Producer-Consumer**(生产者消费者模式):通过缓冲区来协调生产者和消费者线程之间的数据传递。 #### 四、结语 设计模式不仅是解决问题的有效工具,更是编程思维的具体体现。通过深入学习和理解这些模式,...
你可以查看项目中的`producer.py`和`consumer.py`(或者类似命名)文件,了解如何在Python中使用pika或者其他RabbitMQ客户端库来实现这一模式。 在配置消费者时,需要注意确保它们能够正确处理接收到的消息,通常这...
最后,为了保证系统的可扩展性和灵活性,开发者可能还会采用**设计模式**,如生产者-消费者模式(Producer-Consumer Pattern)来协调售票窗口(生产者)和票的库存(消费者)之间的交互。这种模式可以帮助抽象出并发...
10. **设计模式**:为了提高代码的可读性和可维护性,可能会应用一些设计模式,如生产者-消费者模型(Producer-Consumer Pattern)来处理队列中的任务,或者单例模式(Singleton Pattern)来确保类的全局唯一性。...
To that end, this project builds up from the low level KafkaConnection object for handling async requests to/from the kafka server, all the way up to a higher level Producer/Consumer classes.
- **生产者-消费者模式(Producer-Consumer Pattern)**:如果滚动文字的生成和显示是异步的,这种模式可以确保生产者生成文字的速度与消费者(滚动显示)处理速度相匹配。 6. **异常处理**: - **多线程环境下,...
5. **并发模式**:Java中的并发模式涉及到线程安全、同步机制等,如生产者消费者模式(Producer-Consumer)、读写锁模式(Read-Write Lock)等。 6. **设计原则**:如单一职责原则(Single Responsibility ...
在IT行业中,生产者-消费者模型(Producer-Consumer Pattern)是一种经典的并发编程模型,用于解决多线程或分布式系统中的资源共享问题。该模型源于操作系统理论,被广泛应用于各种编程语言和框架中,如Java、C++、...
在这种背景下,生产者-消费者模式(Producer-Consumer Pattern)是一种非常有效的设计模式,用于协调并发任务,使得数据的生产和消费能够高效、有序地进行。本文将深入探讨该模式在.NET 6中的实现,以及如何利用`...
并发集合(Synchronized Collections)、并发集合(Concurrent Collections)、阻塞队列(Blocking Queues)以及生产者-消费者模式(Producer-Consumer Pattern)是构建并发程序的基石。 4. **同步器...