并发编程之生产者和消费者问题

简介: 该博客文章通过Java代码示例介绍了生产者和消费者问题的线程间通信解决方案,演示了如何使用synchronized关键字和wait/notifyAll方法来实现线程间的同步和资源的协调访问。

简单的线程通信,一个线程对数字进行增加操作、另一个线程对线程进行减少操作。

简单解释:线程A对数字进行减少操作,但不会一直让这个数字减少下去。当减少到设定的条件,让其等待,通知其他线程获得该资源。

package com.ProductAndCustomer;

/**
 * 线程之间的通信,生产者和消费者问题
 */
public class Product {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"A").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"B").start();
    }
}


//等待,业务,通知
class Data{
    //资源类
    private int num = 0;

    //增加操作
    public synchronized void increment() throws InterruptedException {
        if(num != 0){
            //等待
            this.wait();
        }
        num ++;
        System.out.println(Thread.currentThread().getName()+"=>"+num);
        //通知其他线程,+1结束
        this.notifyAll();
    }

    //减少操作
    public synchronized void decrement() throws InterruptedException {
        if(num == 0){
            //等待
            this.wait();
        }
        num --;
        System.out.println(Thread.currentThread().getName()+"=>"+num);
        //通知其他线程,-1结束
        this.notifyAll();
    }
}

测试
在这里插入图片描述

在多几个线程

package com.ProductAndCustomer;

/**
 * 线程之间的通信,生产者和消费者问题
 */
public class Product {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"A").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"C").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"D").start();
    }
}


//等待,业务,通知
class Data{
    //资源类
    private int num = 0;

    //增加操作
    public synchronized void increment() throws InterruptedException {
        if(num != 0){
            //等待
            this.wait();
        }
        num ++;
        System.out.println(Thread.currentThread().getName()+"=>"+num);
        //通知其他线程,+1结束
        this.notifyAll();
    }

    //减少操作
    public synchronized void decrement() throws InterruptedException {
        if(num == 0){
            //等待
            this.wait();
        }
        num --;
        System.out.println(Thread.currentThread().getName()+"=>"+num);
        //通知其他线程,-1结束
        this.notifyAll();
    }
}

测试结果
在这里插入图片描述
这里会出现虚假唤醒
查看开发文档可知、需要修改判断语句 if修改为while
在这里插入图片描述
修改后的代码

package com.ProductAndCustomer;

/**
 * 线程之间的通信,生产者和消费者问题
 */
public class Product {
    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"A").start();

        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    data.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"C").start();

        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"D").start();
    }
}


//等待,业务,通知
class Data{
    //资源类
    private int num = 0;

    //增加操作
    public synchronized void increment() throws InterruptedException {
        while(num != 0){
            //等待
            this.wait();
        }
        num ++;
        System.out.println(Thread.currentThread().getName()+"=>"+num);
        //通知其他线程,+1结束
        this.notifyAll();
    }

    //减少操作
    public synchronized void decrement() throws InterruptedException {
        while(num == 0){
            //等待
            this.wait();
        }
        num --;
        System.out.println(Thread.currentThread().getName()+"=>"+num);
        //通知其他线程,-1结束
        this.notifyAll();
    }
}

测试结果
在这里插入图片描述

相关文章
|
容器
多线程学习之生产者和消费者与阻塞队列的关系
多线程学习之生产者和消费者与阻塞队列的关系
55 0
|
消息中间件 Java 测试技术
Java多线程消费消息
关键词:Java,多线程,消息队列,rocketmq 多线程一个用例之一就是消息的快速消费,比如我们有一个消息队列我们希望以更快的速度消费消息,假如我们用的是rocketmq,我们从中获取消息,然后使用多线程处理。
129 0
|
4月前
|
安全
LinkedBlockingQueue实现的生产者和消费者模型
LinkedBlockingQueue实现的生产者和消费者模型
38 1
|
6月前
|
并行计算 安全 Go
可重入锁实现消费者和生产者的例子
【6月更文挑战第28天】本文探讨了Python和Go中使用可重入锁(RLock)进行线程同步以及异步操作。异步存取示例展示了goroutine的并发优势,启动简单且运行异步。goroutine的调度和并发处理能力是其高效并发的关键。
38 0
可重入锁实现消费者和生产者的例子
|
安全 Java
【JUC基础】06. 生产者和消费者问题
学习JUC,就不得不提生产者消费者。生产者消费者模型是一种经典的多线程模型,用于解决生产者和消费者之间的数据交换问题。在生产者消费者模型中,生产者生产数据放入共享的缓冲区中,消费者从缓冲区中取出数据进行消费。在这个过程中,生产者和消费者之间需要保持同步,以避免数据出现错误或重复。今天我们就来说说生产者消费者模型,以及JUC中如何解决该模型的同步问题。
153 0
|
安全 数据处理
线程中的生产者和消费者模式
线程中的生产者和消费者模式
130 0
线程中的生产者和消费者模式
一个简单的生产者和消费者客服实现
一个简单的生产者和消费者客服实现
144 0
|
安全 Java
Java多线程——生产者/消费者问题
生产者/消费者问题
166 0

热门文章

最新文章