首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

多线程必考「生产者 - 消费者」模型,看乔戈里这篇文章就够了

上述描述等着,其实就是用 wait() 来实现; 而通知,就是 notify() 或者 notifyAll() 。 那么基于这种消息通知机制,我们还能够平衡生产者和消费者之间速度差异。...这里我们用到了 2 个队列: 同步队列:对应于我们上一节讲线程状态 Runnable,也就是线程准备就绪,就等着抢资源了。...等待队列:对应于我们上一节讲线程状态 Waiting,也就是等待状态。...() == 0) { //队列产品从无到有,需要通知在等待消费者 queue.notifyAll(); } Random...我们主要逻辑拎出来看: public void run() { synchronized (queue) { while (queue.size() == maxCapacity

49220
您找到你想要的搜索结果了吗?
是的
没有找到

你真的理解生产者消费者模式吗?

生产者-消费者模式 目光从厕所转到饭馆,一个饭馆里通常都有好多厨师以及好多服务员,这里我们厨师称为生产者,服务员称为消费者,厨师和服务员是不直接打交道,而是在厨师做好菜之后放到窗口,服务员从窗口直接菜端走给客人就好了...Food之后,就会调用notifyAll来唤醒等待队列厨师线程们;当消费者线程在wait时候,队列元素肯定是0,此时厨师线程肯定是不会wait,生产过程是被锁对象queue保护,所以在一个厨师线程生产了一个...Food对象之后,就会调用notifyAll来唤醒等待队列服务员线程们。...我们这里生产者-消费者模型是实际使用场景进行了简化,真正实际场景中生产过程和消费过程一般都会很耗时,这些耗时操作最好不要放在同步代码块,这样会造成别的线程长时间阻塞。...如果生产过程和消费过程都放在同步代码块,也就是说在一个厨师炒菜同时不允许别的厨师炒菜,在一个服务员端菜同时不允许别的服务员端菜,这个显然是不合理,大家需要注意这一点。

1.6K20

线程通知与等待

JavaObject类是所有类父类,鉴于继承机制,Java所有的类都需方法放在了Object类里面,其中就包含要说通知与等待。...虽然虚假唤醒在应用实践很少发生,但要防患于未然,做法就是不停地去测试该线程被唤醒状态条件是否满足,不满足则继续等待,也就是说在一个循环中调用**wait()**方法进行防范。...退出循环条件就是满足了唤醒该线程条件。...假如当前线程被虚假唤醒了,但是队列还是没有空余容量,那么当前线程还是会调用wait()方法自己挂起。...while (queue.size() == MAX_SIZE) { // 挂起当前线程,并释放通过同步块获取queue上锁,让消费者线程可以获取该锁,然后获取队列里面的元素

1.1K30

Java线程之间通知与等待,详解!!

JavaObject类是所有类父类,鉴于继承机制,Java所有的类都需方法放在了Object类里面,其中就包含要说通知与等待。...也就是所谓虚假唤醒。 虽然虚假唤醒在应用实践很少发生,但要防患于未然,做法就是不停地去测试该线程被唤醒状态条件是否满足,不满足则继续等待,也就是说在一个循环中调用wait()方法进行防范。...退出循环条件就是满足了唤醒该线程条件。...假如当前线程被虚假唤醒了,但是队列还是没有空余容量,那么当前线程还是会调用wait()方法自己挂起。...while (queue.size() == MAX_SIZE) { // 挂起当前线程,并释放通过同步块获取queue上锁,让消费者线程可以获取该锁,然后获取队列里面的元素

1.7K30

Java并发编程:线程间协作两种方式:wait、notify、notifyAll和Condition

Java并发编程:线程间协作两种方式:wait、notify、notifyAll和Condition   在前面我们将了很多关于同步问题,然而在现实,需要线程之间协作。...因为生产者如果不释放对临界资源占用权,那么消费者就无法消费队列商品,就不会让队列有空间,那么生产者就会一直无限等待下去。...monitor,则只能唤醒其中一个线程;   4)调用notifyAll()方法能够唤醒所有正在等待这个对象monitor线程;   有朋友可能会有疑问:为何这三个不是Thread类声明方法,而是...假若在Thread4调用objectA.notifyAll()方法,则Thread1、Thread2和Thread3三个线程都会被唤醒,至于哪个线程接下来能够获取到objectAmonitor就具体依赖于操作系统调度了...Objectwait();   Conditionsignal()对应Objectnotify();   ConditionsignalAll()对应ObjectnotifyAll()。

79270

Java 线程基础

为了在新线程执行我们代码,必须使用 Thread start 方法。 线程休眠 使用 Thread.sleep 方法可以使得当前正在执行线程进入休眠状态。...所以在其他处于非 Running 状态线程上执行这两个方法是没有意义。这就是为什么这些方法是静态。它们可以在当前正在执行线程工作,并避免程序员错误认为可以在其他非运行线程调用这些方法。...为什么 wait、notify、notifyAll 不定义在 Thread 为什么 wait、notify、notifyAll 要配合 synchronized 使用?...首先,需要了解几个基本知识点: 每一个 Java 对象都有一个与之对应 监视器(monitor) 每一个监视器里面都有一个 对象锁 、一个 等待队列、一个 同步队列 了解了以上概念,我们回过头来理解前面两个问题...,队列当前有:" + queue.size() + "个元素"); } } } } } join 在线程操作,可以使用

42030

Java 多线程系列Ⅲ

定义一个名为SharedBuffer类,它代表共享缓冲区。这个类有两个属性:一个是整型bufferSize,表示缓冲区大小;另一个是队列queue,用于存储数据。...当消费者从缓冲区取出一些数据后,它会调用notifyAll()方法唤醒正在等待生产者线程。...需要注意是,在这个例子我们使用了synchronized关键字来确保同一时刻只有一个线程可以执行put()或get()方法。...wait等待结束条件: 其他线程调用该对象 notify 方法 wait 等待时间超时 (wait 方法提供一个带有 timeout 参数版本, 来指定等待时间) 其他线程调用该等待线程 interrupted...应该使用带有条件wait循环,以便在满足条件时退出等待。 应该小心使用notify()和notifyAll()方法,以避免意外唤醒所有线程而没有处理异常情况。应该在满足条件时再调用这些方法。

7610

Java线程知识点总结

为什么 wait、notify、notifyAll 不定义在 Thread 为什么 wait、notify、notifyAll 要配合 synchronized 使用?...首先,需要了解几个基本知识点: 每一个 Java 对象都有一个与之对应 监视器(monitor) 每一个监视器里面都有一个 对象锁 、一个 等待队列、一个 同步队列 了解了以上概念,我们回过头来理解前面两个问题...,队列当前有:" + queue.size() + "个元素"); } } } } } join 在线程操作,可以使用...所以在其他处于非 Running 状态线程上执行这两个方法是没有意义。这就是为什么这些方法是静态。它们可以在当前正在执行线程工作,并避免程序员错误认为可以在其他非运行线程调用这些方法。...为了在新线程执行我们代码,必须使用 Thread start 方法。

25820

(67) 线程基本协作机制 (上) 计算机程序思维逻辑

上节我们说过,每个对象都有一锁和等待队列,一个线程在进入synchronized代码块时,会尝试获取锁,获取不到的话会把当前线程加入等待队列,其实,除了用于锁等待队列,每个对象还有另一个等待队列,...(); notify做事情就是从条件队列中选一个线程,将其从队列移除并唤醒,notifyAll和notify区别是,它会移除条件队列中所有的线程并全部唤醒。...我们需要进一步理解wait内部过程,虽然是在synchronzied方法内,但调用wait时,线程会释放对象锁,wait具体过程是: 当前线程放入条件等待队列,释放对象锁,阻塞等待,线程状态变为WAITING...或TIMED_WAITING 等待时间到或被其他线程调用notify/notifyAll条件队列移除,这时,要重新竞争对象锁 如果能够获得锁,线程状态变为RUNNABLE,并从wait调用返回 否则...take是给消费者使用,从队列取数据,如果为空就wait,取完之后调用notifyAll,通知可能生产者。

63360

漫画:Object类很大,你忍一下(完结篇)

在上一篇当中,我们提及了Java语言Object类九大方法,并重点讲解了其中getClass(),finalize(),toString(),equals(),hashcode()。...没看过小伙伴,可以点击阅读上一篇:漫画:Object类很大,你忍一下 这一次,我们来重点讲解 wait(),notify(),notifyAll() 这三大方法。 ? ? ? ? ?...// 执行这个方法后,持有此对象监视器线程会进入等待队列,同时释放锁 // 如果不在synchronized修饰方法或代码块里调用,则会抛出IllegalMonitorStateException...(2)在while循环里而不是if语句下使用wait(),确保在线程睡眠前后都检查wait()触发条件(防止虚假唤醒)。 (3)wait()方法必须在多线程共享对象上调用。 ? ?...synchronized (queue){ //(2)在while循环里而不是if语句下使用wait(),确保在线程睡眠前后都检查wait()触发条件(防止虚假唤醒)

25911

并发编程系列之掌握Condition接口使用

并发编程系列之掌握Condition接口使用 1、什么是Condition接口 Condition是jdkjuc包中提供并发等待api,俗称条件等待,条件变量,用于在Lock中提供synchronized...注意,Condition只是一个api接口,具体实现还是依赖于具体lock类,比如使用new ReentrantLock().newCondition(); Objectwait(),notify...(),notifyAll()和synchronized配合使用,可以唤醒一个或者全部 Condition需要和lock实现类配合使用,一个Lock实例可以创建多个Condition,一个条件一个等待集合...,可根据条件精确控制等待线程 多线程读取队列,写入数据后,唤醒读取线程继续执行。...该线程从等待方法返回前必须获得与Condition相关锁。 signal()All:唤醒所有等待线程。能够从等待方法返回线程必须获得与Condition相关锁。

23820

(72) 显式条件 计算机程序思维逻辑

上节我们介绍了显式锁,本节介绍关联显式条件,介绍其用法和原理。显式条件也可以被称做条件变量、条件队列、或条件,后文我们可能会交替使用。...,不要将signal/signalAll与notify/notifyAll混淆,notify/notifyAll是Object定义方法,Condition对象也有,稍不注意就会误用,比如,对上面例子...生产者/消费者模式 在67节,我们用wait/notify实现了生产者/消费者模式,我们提到了wait/notify一个局限,它只能有一个条件等待队列,分析等待条件也很复杂。...在生产者/消费者模式,其实有两个条件,一个与队列满有关,一个与队列空有关。使用显式锁,可以创建多个条件等待队列。...transient Node lastWaiter; ConditionObject是AQS成员内部类,它可以直接访问AQS数据,比如AQS定义锁等待队列

72360

Java 并发编程之美-线程相关基础知识

Java 我们启动 main 函数时候其实就启动了一个 JVM 进程,而 main 函数所在线程就是这个进程一个线程,也叫做主线程。 ?...虽然虚假唤醒在应用实践很少发生,但是还是需要防范于未然,做法就是不停去测试该线程被唤醒条件是否满足,不满足则继续等待,也就是说在一个循环中去调用 wait() 方法进行防范,退出循环条件条件满足了唤醒该线程...,这里使用循环就是为了避免上面说虚假唤醒问题,这里假如当前线程虚假唤醒了,但是队列还是没有空余容量的话,当前线程还是会调用 wait() 自己挂起。...//生产线程synchronized (queue) { //消费队列满,则等待队列空闲 while (queue.size() == MAX_SIZE) { try...(); } } //消费线程synchronized (queue) { //消费队列为空 while (queue.size() == 0) {

64830

wait和notify实现线程之间通信

为什么需要线程通信 线程是并发并行执行,表现出来是线程随机执行,但是我们在实际应用对线程执行顺序是有要求,这就需要用到线程通信 线程通信为什么不使用优先级来来解决线程运行顺序?...进入等待线程,重新竞争对象锁 notifyAll():如果有多个线程等待,notifyAll是全部唤醒 ,notify是随机唤醒一个 ‍️注意: 这几个方法都属于Object类方法 必须使用在...()方法 调用wait方法后: 使执行当前代码线程进行等待(线程放在等待队列) 释放当前锁 满足一定条件时被唤醒,重新尝试获取锁 wait等待结束条件: 其他线程调用该对象notify...队列时候,出队列就堵塞等待(消费),直到有其他线程往队列插入元素 1....标准库阻塞队列 在 Java 标准库内置了阻塞队列, 如果我们需要在一些程序中使用阻塞队列, 直接使用标准库即可 BlockingQueue 是一个接口.

18530

如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

如果某些线程在等待某些条件触发,那当那些条件为真时,你可以用 notify 和 notifyAll 来通知那些等待线程重新开始运行。...不同之处在于,notify 仅仅通知一个线程,并且我们不知道哪个线程会收到通知,然而 notifyAll 会通知所有等待线程。...因为线程是在某些条件下等待——在我们例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等待”,你可能直觉就会写一个if语句。...我们在while(queue.size == maxSize)循环语句中检查这个条件。...请注意到我们在做这个检查条件之前已经在队列对象上使用了synchronized关键词,因而其它线程不能在我们检查条件时改变这个队列

84210

如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

如果某些线程在等待某些条件触发,那当那些条件为真时,你可以用 notify 和 notifyAll 来通知那些等待线程重新开始运行。...不同之处在于,notify 仅仅通知一个线程,并且我们不知道哪个线程会收到通知,然而 notifyAll 会通知所有等待线程。...因为线程是在某些条件下等待——在我们例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等待”,你可能直觉就会写一个if语句。...我们在while(queue.size == maxSize)循环语句中检查这个条件。...请注意到我们在做这个检查条件之前已经在队列对象上使用了synchronized关键词,因而其它线程不能在我们检查条件时改变这个队列

96320

Java并发编程实战系列14之构建自定义同步工具 (Building Custom Synchronizers)

那么我们想如果这种轮询和休眠dummy方式不用,而是存在某种挂起线程方案,并且这种方法能够确保党某个条件成真时候立刻唤醒线程,那么将极大简化实现工作,这就是条件队列实现。...对象内置锁(intrinsic lock )和内置条件队列是关联,要调用X条件队列任何一个方法,都必须持有对象X上锁。...调用notify和notifyAll也得持有与条件队列对象相关联锁。...所以在BoundedBuffer这种累,多个线程可能在同一个条件队列上等待不同条件谓词,所以notifyAll经常通知不是同一个类型需求。...如果想编写一个带有多个条件谓词并发对象,或者想获得除了条件队列可见性之外更多控制权,可以使用Lock和Condition,而不是内置锁和条件队列,这更加灵活。

1.2K60
领券