当前位置: 首页 > news >正文

网络公司网站建设seo店铺描述例子

网络公司网站建设,seo店铺描述例子,网站备案幕布 下载,制作免费网站的平台文章目录 传统解法解法一:传统解法 (synchronized wait/notifyAll) 的流程解说核心机制生产者流程 (produce)消费者流程 (consume)关键点与缺点 多条件解法解法二:多条件解法 (ReentrantLock Condition) 的流程解说核心机制生产者流程 (produce)消费者…

文章目录

  • 传统解法
      • 解法一:传统解法 (`synchronized` + `wait/notifyAll`) 的流程解说
        • 核心机制
        • 生产者流程 (`produce`)
        • 消费者流程 (`consume`)
        • 关键点与缺点
  • 多条件解法
      • 解法二:多条件解法 (`ReentrantLock` + `Condition`) 的流程解说
        • 核心机制
        • 生产者流程 (`produce`)
        • 消费者流程 (`consume`)
        • 关键优势:精确唤醒

传统解法

package JUC_练习题.生产者消费者.传统解法;import java.util.LinkedList;
import java.util.Queue;public class ProducerConsumerSynchronized {// 共享的缓冲区static class Buffer {private final Queue<Integer> queue = new LinkedList<>();private final int capacity;public Buffer(int capacity) {this.capacity = capacity;}// 生产方法public synchronized void produce(int item) throws InterruptedException {// 如果缓冲区满了,生产者等待while (queue.size() == capacity) {System.out.println(Thread.currentThread().getName() + " 缓冲区满了,等待消费...");wait(); // 释放锁并等待}// 生产物品queue.offer(item);System.out.println(Thread.currentThread().getName() + " 生产了: " + item +",当前数量: " + queue.size());// 通知消费者可以消费了notifyAll();}// 消费方法public synchronized int consume() throws InterruptedException {// 如果缓冲区空了,消费者等待while (queue.isEmpty()) {System.out.println(Thread.currentThread().getName() + " 缓冲区空了,等待生产...");wait(); // 释放锁并等待}// 消费物品int item = queue.poll();System.out.println(Thread.currentThread().getName() + " 消费了: " + item +",剩余数量: " + queue.size());// 通知生产者可以生产了notifyAll();return item;}}public static void main(String[] args) {Buffer buffer = new Buffer(5); // 容量为5的缓冲区// 创建2个生产者for (int i = 1; i <= 2; i++) {new Thread(() -> {try {for (int j = 1; j <= 5; j++) {buffer.produce(j);Thread.sleep(100); // 模拟生产时间}} catch (InterruptedException e) {e.printStackTrace();}}, "生产者" + i).start();}// 创建3个消费者for (int i = 1; i <= 3; i++) {new Thread(() -> {try {for (int j = 1; j <= 3; j++) {buffer.consume();Thread.sleep(200); // 模拟消费时间}} catch (InterruptedException e) {e.printStackTrace();}}, "消费者" + i).start();}}
}

好的,我们来分别对这两个经典的生产者-消费者模型的解法进行详细的流程解说。


解法一:传统解法 (synchronized + wait/notifyAll) 的流程解说

这个方案是Java最基础的线程同步与通信方式,它依赖于每个对象都拥有的“监视器锁”。

核心机制
  • Buffer 对象本身。当一个线程进入任何一个 synchronized 方法(produceconsume)时,它就获得了 buffer 对象的锁。
  • 等待队列:每个锁对象(这里是buffer)只有一个等待队列(Wait Set)。所有调用 wait() 的线程,不管是生产者还是消费者,都会进入这同一个队列里等待。
  • 通信:通过 wait() 释放锁并等待,通过 notifyAll() 唤醒等待队列中的所有线程。
生产者流程 (produce)
  1. 一个生产者线程(比如“生产者1”)调用 buffer.produce()
  2. 它尝试获取 buffer 对象的锁。如果锁空闲,它就成功获得锁。此时,其他任何线程(包括其他生产者和所有消费者)都无法进入 produceconsume 方法。
  3. 它进入 while (queue.size() == capacity) 循环检查条件。
    • 如果缓冲区满了
      • 打印“缓冲区满了,等待消费…”。
      • 调用 wait()。此时,该生产者线程会立即释放它持有的 buffer,并进入 buffer 对象的等待队列中休眠。
    • 如果缓冲区未满
      • 跳出 while 循环。
      • queue 中添加一个物品 (queue.offer(item))。
      • 打印生产信息。
      • 调用 notifyAll()。这个动作会唤醒所有正在 buffer 等待队列中休眠的线程(包括可能在等待的其他生产者所有消费者)。
  4. produce 方法执行完毕,线程退出 synchronized 方法,正常释放锁
消费者流程 (consume)
  1. 一个消费者线程(比如“消费者1”)调用 buffer.consume()
  2. 它获取 buffer 对象的锁。
  3. 它进入 while (queue.isEmpty()) 循环检查条件。
    • 如果缓冲区是空的
      • 打印“缓冲区空了,等待生产…”。
      • 调用 wait()释放 buffer并进入等待队列。
    • 如果缓冲区不空
      • 跳出 while 循环。
      • queue 中取出一个物品 (queue.poll())。
      • 打印消费信息。
      • 调用 notifyAll(),唤醒所有在等待的线程。
  4. consume 方法执行完毕,线程退出 synchronized 方法,正常释放锁
关键点与缺点
  • 优点:实现简单,是Java内置的机制。
  • 缺点:效率较低,存在“惊群效应” (Thundering Herd)。当一个生产者调用 notifyAll() 时,它会唤醒所有线程。但此时缓冲区可能只多了一个位置,那么被唤醒的其他生产者线程会发现条件依然不满足(还是满的),于是它们白白醒来一次,检查完条件后又得继续 wait()。这造成了不必要的线程上下文切换和CPU资源浪费。

多条件解法

package JUC_练习题.生产者消费者.可重入锁和多条件;import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;public class ProducerConsumerReentrantLock {// 共享的缓冲区static class Buffer {private final Queue<Integer> queue = new LinkedList<>();private final int capacity;// ReentrantLock 和两个条件变量private final ReentrantLock lock = new ReentrantLock();private final Condition notFull = lock.newCondition();  // 缓冲区不满的条件private final Condition notEmpty = lock.newCondition(); // 缓冲区不空的条件public Buffer(int capacity) {this.capacity = capacity;}// 生产方法public void produce(int item) throws InterruptedException {lock.lock(); // 获取锁try {// 如果缓冲区满了,在 notFull 条件上等待while (queue.size() == capacity) {System.out.println(Thread.currentThread().getName() +" 缓冲区满了,在notFull条件上等待...");notFull.await(); // 释放锁并等待}// 生产物品queue.offer(item);System.out.println(Thread.currentThread().getName() + " 生产了: " + item +",当前数量: " + queue.size());// 通知在 notEmpty 条件上等待的消费者notEmpty.signal(); // 精确通知消费者} finally {lock.unlock(); // 释放锁}}// 消费方法public int consume() throws InterruptedException {lock.lock(); // 获取锁try {// 如果缓冲区空了,在 notEmpty 条件上等待while (queue.isEmpty()) {System.out.println(Thread.currentThread().getName() +" 缓冲区空了,在notEmpty条件上等待...");notEmpty.await(); // 释放锁并等待}// 消费物品int item = queue.poll();System.out.println(Thread.currentThread().getName() + " 消费了: " + item +",剩余数量: " + queue.size());// 通知在 notFull 条件上等待的生产者notFull.signal(); // 精确通知生产者return item;} finally {lock.unlock(); // 释放锁}}}public static void main(String[] args) {Buffer buffer = new Buffer(5); // 容量为5的缓冲区// 创建2个生产者for (int i = 1; i <= 2; i++) {new Thread(() -> {try {for (int j = 1; j <= 5; j++) {buffer.produce(j);Thread.sleep(100); // 模拟生产时间}} catch (InterruptedException e) {e.printStackTrace();}}, "生产者" + i).start();}// 创建3个消费者for (int i = 1; i <= 3; i++) {new Thread(() -> {try {for (int j = 1; j <= 3; j++) {buffer.consume();Thread.sleep(200); // 模拟消费时间}} catch (InterruptedException e) {e.printStackTrace();}}, "消费者" + i).start();}}
}

解法二:多条件解法 (ReentrantLock + Condition) 的流程解说

这个方案是JUC(java.util.concurrent)包提供的更现代、更灵活的解决方案。

核心机制
  • :一个显式的 ReentrantLock 对象。通过 lock.lock()lock.unlock() 来控制。
  • 等待队列不再是单一的队列。我们从一个 Lock 对象可以创建出多个 Condition 对象,每个 Condition 对象都拥有自己独立的等待队列
    • notFull 条件:管理所有因“缓冲区已满”而等待的生产者线程。
    • notEmpty 条件:管理所有因“缓冲区为空”而等待的消费者线程。
  • 通信await() 相当于 wait()signal() 相当于 notify()。因为我们有两个独立的条件队列,所以可以实现精确唤醒
生产者流程 (produce)
  1. 生产者线程调用 produce()

  2. 它调用 lock.lock() 获取锁。

  3. 进入 try...finally 块(确保锁一定会被释放)。

  4. 检查 while (queue.size() == capacity) 条件。

    • 如果缓冲区满了
      • 打印“在notFull条件上等待…”。
      • 调用 notFull.await()。生产者线程会释放 lock,并进入 notFull 自己的等待队列中休眠。
    • 如果缓冲区未满
      • 生产物品。
      • 打印信息。
      • 关键一步:调用 notEmpty.signal()。它只会唤醒一个正在 notEmpty 条件队列中等待的线程(也就是一个消费者),而绝对不会去打扰任何在 notFull 队列里等待的其他生产者。
  5. finally 块中的 lock.unlock() 被执行,释放锁。

消费者流程 (consume)
  1. 消费者线程调用 consume()

  2. 调用 lock.lock() 获取锁。

  3. 检查 while (queue.isEmpty()) 条件。

    • 如果缓冲区是空的
      • 打印“在notEmpty条件上等待…”。
      • 调用 notEmpty.await()。消费者线程会释放 lock,并进入 notEmpty 自己的等待队列中休眠。
    • 如果缓冲区不空
      • 消费物品。
      • 打印信息。
      • 关键一步:调用 notFull.signal()。它只会唤醒一个正在 notFull 条件队列中等待的线程(也就是一个生产者)。
  4. finally 块中的 lock.unlock() 被执行,释放锁。

关键优势:精确唤醒
  • 效率高ReentrantLock + Condition 的方案通过分离等待队列,实现了精确唤醒。生产者只唤醒消费者,消费者只唤醒生产者。这完全避免了“惊群效应”,使得线程调度非常高效。
  • 逻辑清晰:代码的意图更明确,notFull.await() 就是在等“不满”的条件,notEmpty.signal() 就是在通知“不空”这个消息。
  • 功能更强ReentrantLockCondition 提供了更丰富的功能,如可中断的等待、定时的等待、公平锁等。

总而言之,多条件解法是传统解法的一个全面升级,它通过更精细的控制,解决了传统解法的效率瓶颈。

http://www.hrbkazy.com/news/7317.html

相关文章:

  • 物联网小项目河南靠谱seo电话
  • wordpress留言板隐藏seo网站营销推广公司
  • 做我女朋友网站p0rn视频全球搜索引擎市场份额
  • 欧 美 做 爱 视频网站抖音seo关键词排名技术
  • 政府 网站建设方案快速排名上
  • 企业网站建设相关书籍在线阅读百度收录关键词查询
  • 用什么java软件做网站什么软件可以免费引流
  • 黑帽seo寄生虫seo课程培训
  • 成都网站建设推广在地推扫码平台
  • 大兴 网站建设做网络推广的网站有哪些
  • 西安网站建设盈科产品线上推广渠道
  • 无锡做网站f7wl网站链接查询
  • 兼容模式网站错位怎么做网络营销平台
  • 论坛门户静态网页模板搜索引擎优化面对哪些困境
  • 品古典家具网站模板百度指数在线查询工具
  • 移动医护网站建设利弊百度经验app下载
  • 沈阳网站制作培训什么是seo?
  • 宜春做网站哪里好站长之家最新网站
  • 专业做网站建设公司如何注册一个平台
  • 购物网站排名2017凡科建站教程
  • 网站logo如何修改seo排名影响因素主要有
  • 无锡网站建设咨询百度知道个人中心
  • 别人怎么看见我做的网站湖北百度推广电话
  • 做的丑的网站有哪些知乎西安seo外包优化
  • 把一个网站挂到网上要怎么做免费网站建站
  • 带地板翻转的网站怎么做百度推广教程视频教程
  • 易语言网站开发教程青岛网站seo诊断
  • 用模板做网站的方法郑州搜索引擎优化公司
  • 有限公司网站建设 中企动力佛山百度搜索引擎优化的推广计划
  • 移动端网站提交提交it培训机构哪家好