目录

1.生产者消费者模型

1.1 单个生产者单个消费者

1.1.1知识点

1.1.2案例分析

1.1.3代码概述

1.1.4特点

1.1.5代码

1.2 多个生产者多个消费者

线程同步

线程通信

关键词解释

代码

2.仓储模型

2.1 一个生产者一个消费者

2.1.1 知识点

2.1.2 案例分析

2.1.3 代码概述

2.1.4代码

2.2 多个生产者多个消费者

2.2.1 知识点

2.2.2 案例分析

2.2.3 代码概述

知识点拓展

2.2.4代码


1.生产者消费者模型

1.1 单个生产者单个消费者
1.1.1知识点
  • 生产者消费者模型:一种常见的并发模式,用于协调生产者和消费者之间的工作流程,确保数据的有效生产和消费。

  • Java中的线程同步和通信:使用synchronized关键字和wait/notify方法来控制线程间的协调和通信。

1.1.2案例分析
  • 产品类 (Phone): 拥有品牌 (brand) 和价格 (price) 属性。

  • 生产者线程 (Producer): 负责生产产品,即设置Phone的品牌和价格。

  • 消费者线程 (Consumer): 负责消费产品,即读取Phone的品牌和价格。

1.1.3代码概述
  1. Phone类

    • 属性:brand(品牌)、price(价格)、store(库存标志)。

    • 方法:getters、setters、toString()。

  2. Producer类

    • run方法中,交替生产华为和小米手机。

    • 使用synchronized来确保线程安全。

    • 当存在库存时,使用wait方法让生产者线程等待。

  3. Consumer类

    • run方法中,循环消费手机。

    • 使用synchronized来确保线程安全。

    • 当无库存时,使用wait方法让消费者线程等待。

    • 消费后打印手机信息,并通知生产者继续生产。

1.1.4特点
  • 线程间的协作:通过waitnotify方法实现线程间的协作。

  • 控制生产消费节奏:保证生产一个消费一个的节奏,避免资源浪费和冲突。

  • 解决脏数据问题:通过线程同步机制,确保数据的准确性和一致性。 这个案例是生产者消费者问题的典型应用,展示了如何在Java中使用线程同步和通信机制来解决并发问题。

1.1.5代码
package com.qf.producer_consumer_01;
​
public class Test01 {
    /**
     * 知识点:生产者消费者模型 - 单个生产者单个消费者
     * 
     * 分析:
     *      产品类 - Phone:属性(brand,price)
     *      生产者线程 - Producer
     *      消费者线程 - Consumer
     * 最终的目的:生产一个、消费一个
     * 
     * 步骤:
     *      1.多个线程(生产者线程、消费者线程)操作同一个资源(产品类的对象)
     *      2.多个产品之间来回切换(华为 <--> 小米)
     *          null -- 0.0
     *          华为 -- 0.0
     *          小米 -- 3999
     *          华为 -- 1999
     *          脏数据的解决思路:加锁
     *      3.生产一个消费一个
     *          
     */
    public static void main(String[] args) {
        
        //brand - null
        //price - 0.0
        Phone phone = new Phone();
        
        Producer p = new Producer(phone);
        Consumer c = new Consumer(phone);
        p.start();
        c.start();      
    }
}
package com.qf.producer_consumer_01;
​
//产品类
public class Phone {
​
    private String brand;
    private double price;
    private boolean store;
    
    public Phone() {
    }
​
    public Phone(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }
​
    public String getBrand() {
        return brand;
    }
​
    public void setBrand(String brand) {
        this.brand = brand;
    }
​
    public double getPrice() {
        return price;
    }
​
    public void setPrice(double price) {
        this.price = price;
    }
    
    public boolean isStore() {
        return store;
    }
​
    public void setStore(boolean store) {
        this.store = store;
    }
​
    @Override
    public String toString() {
        return "Phone [brand=" + brand + ", price=" + price + "]";
    }
}
​
package com.qf.producer_consumer_01;
​
//生产者线程
public class Producer extends Thread{
    
    private Phone phone;
​
    public Producer(Phone phone) {
        this.phone = phone;
    }
​
    @Override
    public void run() {
        boolean flag = true;
        while(true){
            synchronized(phone){
                if(phone.isStore()){//有库存
                    //等待
                    //1.将当前线程记录在对象监视器中(记录当前线程进入到阻塞状态)
                    //2.释放锁资源(解锁)
                    //3.当前线程进入到阻塞状态
                    try {
                        phone.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if(flag){
                    phone.setBrand("华为");
                    phone.setPrice(3999);
                }else{
                    phone.setBrand("小米");
                    phone.setPrice(1999);
                }
                flag = !flag;
                phone.setStore(true);
                //唤醒:唤醒的是对象监视器中随机一个等待的线程,唤醒的线程进入到就绪态
                phone.notify();
            }
        }
    }
}
​
package com.qf.producer_consumer_01;
​
//消费者线程
public class Consumer extends Thread{
    
    private Phone phone;
​
    public Consumer(Phone phone) {
        this.phone = phone;
    }
​
    @Override
    public void run() {
        while(true){
            synchronized(phone){
                if(!phone.isStore()){//没有库存
                    try {
                        //等待:
                        //1.将当前线程记录在对象监视器中(记录当前线程进入到阻塞状态)
                        //2.释放锁资源(解锁)
                        //3.当前线程进入到阻塞状态
                        phone.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(phone.getBrand() + " -- " + phone.getPrice());
                phone.setStore(false);
                //唤醒:唤醒的是对象监视器中随机一个等待的线程,唤醒的线程进入到就绪态
                phone.notify();
            }
        }
    }
}
​

1.2 多个生产者多个消费者

线程同步

在多线程环境中,确保数据一致性和避免线程间的冲突是必须的。Java中,synchronized关键字用于在对象上加锁,确保一次只有一个线程可以访问该对象的同步代码块或方法。

线程通信

wait()notify()notifyAll()是Object类的一部分,用于线程间的通信。当一个线程调用共享对象的wait()方法时,它进入等待状态直到另一个线程调用该对象的notify()notifyAll()方法。

关键词解释
  • synchronized: Java关键字,用于创建同步代码块或方法,确保多个线程访问共享资源时的同步和数据一致性。

  • wait(): 当一个线程执行到wait()方法时,它会释放持有的锁并进入等待状态,直到被notify()notifyAll()唤醒。

  • notify(): 用于唤醒在同一个对象上调用wait()方法而进入等待状态的单个线程。

  • notifyAll(): 用于唤醒所有在同一个对象上调用wait()方法而进入等待状态的线程。在多个生产者和消费者的场景中,使用notifyAll()可以避免某些线程永远处于等待状态(即线程假死)。

代码

synchronized用于确保在生产或消费手机对象时不会有多个线程同时操作。wait()notifyAll()用于控制生产者和消费者之间的协作,其中wait()使当前线程等待,直到另一个线程调用notifyAll()`。这样,就可以在生产者和消费者之间有效地协调工作,避免数据不一致或资源浪费。

package com.qf.producer_consumer_02;
​
public class Test01 {
    /**
     * 知识点:生产者消费者模型 - 多个生产者多个消费者
     * 
     * 分析:
     *      产品类 - Phone:属性(brand,price)
     *      生产者线程 - Producer
     *      消费者线程 - Consumer
     * 最终的目的:生产一个、消费一个
     * 
     * 步骤:
     *      1.多个线程(生产者线程、消费者线程)操作同一个资源(产品类的对象)
     *      2.多个产品之间来回切换(华为 <--> 小米)
     *          null -- 0.0
     *          华为 -- 0.0
     *          小米 -- 3999
     *          华为 -- 1999
     *          脏数据的解决思路:加锁
     *      3.生产一个消费一个
     *          
     */
    public static void main(String[] args) {
        
        //brand - null
        //price - 0.0
        Phone phone = new Phone();
        
        Producer p1 = new Producer(phone);
        Producer p2 = new Producer(phone);
        Consumer c1 = new Consumer(phone);
        Consumer c2 = new Consumer(phone);
        p1.start();
        p2.start();
        c1.start();
        c2.start();
        
    }
}
​
package com.qf.producer_consumer_02;
​
//产品类
public class Phone {
​
    private String brand;
    private double price;
    private boolean store;
    
    public Phone() {
    }
​
    public Phone(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }
​
    public String getBrand() {
        return brand;
    }
​
    public void setBrand(String brand) {
        this.brand = brand;
    }
​
    public double getPrice() {
        return price;
    }
​
    public void setPrice(double price) {
        this.price = price;
    }
    
    public boolean isStore() {
        return store;
    }
​
    public void setStore(boolean store) {
        this.store = store;
    }
}
package com.qf.producer_consumer_02;
​
//消费者线程
public class Consumer extends Thread{
    
    private Phone phone;
​
    public Consumer(Phone phone) {
        this.phone = phone;
    }
​
    @Override
    public void run() {
        while(true){
            synchronized(phone){
                while(!phone.isStore()){//没有库存
                    try {
                        //等待:
                        //1.将当前线程记录在对象监视器中(记录当前线程进入到阻塞状态)
                        //2.释放锁资源(解锁)
                        //3.当前线程进入到阻塞状态
                        phone.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(phone.getBrand() + " -- " + phone.getPrice());
                phone.setStore(false);
                //唤醒:唤醒对象监视器中所有的线程
                phone.notifyAll();
            }
        }
    }
}
​
package com.qf.producer_consumer_02;
​
//生产者线程
public class Producer extends Thread{
    
    private Phone phone;
​
    public Producer(Phone phone) {
        this.phone = phone;
    }
​
    @Override
    public void run() {
        boolean flag = true;
        while(true){
            synchronized(phone){
                while(phone.isStore()){//有库存
                    //等待
                    //1.将当前线程记录在对象监视器中(记录当前线程进入到阻塞状态)
                    //2.释放锁资源(解锁)
                    //3.当前线程进入到阻塞状态
                    try {
                        phone.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if(flag){
                    phone.setBrand("华为");
                    phone.setPrice(3999);
                }else{
                    phone.setBrand("小米");
                    phone.setPrice(1999);
                }
                flag = !flag;
                phone.setStore(true);
                //唤醒:唤醒对象监视器中所有的线程
                phone.notifyAll();
            }
        }
    }
}

2.仓储模型

2.1 一个生产者一个消费者

2.1.1 知识点
  • 仓储模型:一种协调生产者和消费者之间生产和消费的模式。

  • Java中的线程同步和通信:使用synchronized关键字和wait/notify方法来控制线程间的同步和通信。

2.1.2 案例分析
  • 产品类 (Cake): 具有品牌(brand)、价格(price)和时间(datetime)属性。

  • 仓库类 (Store): 管理产品的仓储,包括最大容量(maxCapacity)、当前容量(curCapacity)和产品列表(list)。

  • 生产者线程 (Producer): 生产产品并存入仓库。

  • 消费者线程 (Consumer): 从仓库中取出并消费产品。

2.1.3 代码概述
  1. Store类

    • 使用synchronized实现线程同步。

    • push方法:当仓库容量满时,使用wait方法使生产者等待;否则,生产产品并通知消费者。

    • pop方法:当仓库为空时,使用wait方法使消费者等待;否则,消费产品并通知生产者。

  2. Cake类

    • 定义产品的属性和方法。

  3. Producer类

    • 循环生产产品并调用push方法存入仓库。

  4. Consumer类

    • 循环从仓库中取出并消费产品。

2.1.4代码
package com.qf.store_01;
​
public class Test01 {
    /**
     * 知识点:仓储模型 - 一个生产者一个消费者
     * 
     * 分析:
     *      产品类 - Cake(brand、price、datetime)
     *      仓库类 - Store(maxCapacity、curCapacity、list)
     *      生产者线程 - Producer
     *      消费者线程 - Consumer
     *      注意:先生产的先卖出 -- 队列模式
     * 
     * 经验:对象监视器如何选择?
     *      锁对象
     * 
     */
    public static void main(String[] args) {    
        Store store = new Store();      
        Producer p = new Producer(store);
        Consumer c = new Consumer(store);       
        p.start();=
        c.start();      
    }
}
package com.qf.store_01;
​
import java.util.LinkedList;
​
public class Store {
    
    private static final int DEFAULT_INIT_CAPACITY = 20;
    private int maxCapacity;
    private int curCapacity;
    private LinkedList<Cake> list;
    
    public Store() {
        maxCapacity = DEFAULT_INIT_CAPACITY;
        list = new LinkedList<>();
    }
​
    public Store(int maxCapacity) {
        this.maxCapacity = maxCapacity;
        list = new LinkedList<>();
    }
    
    //入库
    public synchronized void push(Cake cake){
        if(curCapacity >= maxCapacity){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        list.add(cake);
        curCapacity++;
        System.out.println("入库,当前库存为:" + curCapacity);
        this.notify();
    }
    
    
    //出库
    public synchronized Cake pop(){
        if(curCapacity <= 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Cake cake = list.removeFirst();
        curCapacity--;
        System.out.println("出库,当前的库存为:" + curCapacity + ",卖出的产品是:" + cake);
        this.notify();
        return cake;
    }
    
}
​
package com.qf.store_01;
​
public class Cake {
    
    private String brand;
    private double price;
    private String datetime;
​
    public Cake() {
    }
​
    public Cake(String brand, double price, String datetime) {
        this.brand = brand;
        this.price = price;
        this.datetime = datetime;
    }
​
    public String getBrand() {
        return brand;
    }
​
    public void setBrand(String brand) {
        this.brand = brand;
    }
​
    public double getPrice() {
        return price;
    }
​
    public void setPrice(double price) {
        this.price = price;
    }
​
    public String getDatetime() {
        return datetime;
    }
​
    public void setDatetime(String datetime) {
        this.datetime = datetime;
    }
​
    @Override
    public String toString() {
        return "Cake [brand=" + brand + ", price=" + price + ", datetime=" + datetime + "]";
    }
}
​
package com.qf.store_01;
​
public class Consumer extends Thread{
    
    private Store store;
    
    public Consumer(Store store) {
        this.store = store;
    }
​
    @Override
    public void run() {
        while(true){
            store.pop();
        }
    }
}
​
package com.qf.store_01;
​
import java.time.LocalDateTime;
​
public class Producer extends Thread{
    
    private Store store;
    
    public Producer(Store store) {
        this.store = store;
    }
​
    @Override
    public void run() {
        while(true){
            Cake cake = new Cake("桃李蛋糕", 2.5, LocalDateTime.now().toString());
            store.push(cake);
        }
    }
}
​

2.2 多个生产者多个消费者

2.2.1 知识点
  • 与2.1相同,但在多个生产者和消费者的情况下,线程同步和通信更为复杂。

2.2.2 案例分析
  • 与2.1相同,但有多个生产者和消费者。

2.2.3 代码概述
  • Store类

    • 与2.1相同,但在pushpop方法中使用notifyAll而非notify,以唤醒所有等待的线程。

  • Producer类和Consumer类

    • 与2.1相同,但存在多个实例。

知识点拓展
  • synchronized: Java关键字,用于线程同步,确保一次只有一个线程可以访问共享资源。

  • wait(): 使当前线程等待,直到另一个线程调用notify()notifyAll()

  • notify(): 唤醒在该对象监视器上等待的单个线程。

  • notifyAll(): 唤醒在该对象监视器上等待的所有线程,通常在多个生产者和消费者的场景中使用。

2.2.4代码
package com.qf.store_02;
​
public class Test01 {
    /**
     * 知识点:仓储模型 - 多个生产者多个消费者
     * 
     * 分析:
     *      产品类 - Cake(brand、price、datetime)
     *      仓库类 - Store(maxCapacity、curCapacity、list)
     *      生产者线程 - Producer
     *      消费者线程 - Consumer
     *      注意:先生产的先卖出 -- 队列模式
     * 
     * 经验:对象监视器如何选择?
     *      锁对象
     * 
     */
    public static void main(String[] args) {        
        Store store = new Store();      
        Producer p1 = new Producer(store);
        Producer p2 = new Producer(store);
        Consumer c1 = new Consumer(store);
        Consumer c2 = new Consumer(store);      
        p1.start();
        p2.start();
        c1.start();
        c2.start();     
    }
}
package com.qf.store_02;
​
public class Cake {
    
    private String brand;
    private double price;
    private String datetime;
​
    public Cake() {
    }
​
    public Cake(String brand, double price, String datetime) {
        this.brand = brand;
        this.price = price;
        this.datetime = datetime;
    }
​
    public String getBrand() {
        return brand;
    }
​
    public void setBrand(String brand) {
        this.brand = brand;
    }
​
    public double getPrice() {
        return price;
    }
​
    public void setPrice(double price) {
        this.price = price;
    }
​
    public String getDatetime() {
        return datetime;
    }
​
    public void setDatetime(String datetime) {
        this.datetime = datetime;
    }
​
    @Override
    public String toString() {
        return "Cake [brand=" + brand + ", price=" + price + ", datetime=" + datetime + "]";
    }
}
​
package com.qf.store_02;
​
import java.util.LinkedList;
​
public class Store {
    
    private static final int DEFAULT_INIT_CAPACITY = 20;
    private int maxCapacity;
    private int curCapacity;
    private LinkedList<Cake> list;
    
    public Store() {
        maxCapacity = DEFAULT_INIT_CAPACITY;
        list = new LinkedList<>();
    }
​
    public Store(int maxCapacity) {
        this.maxCapacity = maxCapacity;
        list = new LinkedList<>();
    }
    
    //入库
    public synchronized void push(Cake cake){
        while(curCapacity >= maxCapacity){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        list.add(cake);
        curCapacity++;
        System.out.println("入库,当前库存为:" + curCapacity);
        this.notifyAll();
    }
    
    
    //出库
    public synchronized Cake pop(){
        while(curCapacity <= 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Cake cake = list.removeFirst();
        curCapacity--;
        System.out.println("出库,当前的库存为:" + curCapacity + ",卖出的产品是:" + cake);
        this.notifyAll();
        return cake;
    }
    
}
​
package com.qf.store_02;
​
public class Consumer extends Thread{
    
    private Store store;
    
    public Consumer(Store store) {
        this.store = store;
    }
​
    @Override
    public void run() {
        while(true){
            store.pop();
        }
    }
}
package com.qf.store_02;
​
import java.time.LocalDateTime;
​
public class Producer extends Thread{
    
    private Store store;
    
    public Producer(Store store) {
        this.store = store;
    }
​
    @Override
    public void run() {
        while(true){
            Cake cake = new Cake("桃李蛋糕", 2.5, LocalDateTime.now().toString());
            store.push(cake);
        }
    }
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐