JAVA生产者消费者(线程同步)代码学习示例

JAVA生产者消费者(线程同步)代码学习示例

什么是生产者消费者模型

生产者消费者模型是一种常用的线程同步模型,它通过在多个线程之间协调共享资源的访问,来提高系统的效率和可靠性。在生产者消费者模型中,生产者线程负责生成数据,消费者线程负责消费数据,两者通过共享队列来协作,实现生产与消费的同步和协调。

学习示例1:基本实现

假设有一个生产者线程和一个消费者线程共享一个阻塞队列,生产者线程每次在队列尾部添加一个数字,消费者线程每次从队列头部获取一个数字,并将它打印出来。代码如下:

import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumerExample {

    private Queue<Integer> queue = new LinkedList<>();
    private static final int MAX_SIZE = 10;

    public static void main(String[] args) throws InterruptedException {
        ProducerConsumerExample example = new ProducerConsumerExample();

        Thread producerThread = new Thread(() -> {
            for (int i = 1; i <= 20; i++) {
                try {
                    example.produce(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread consumerThread = new Thread(() -> {
            for (int i = 1; i <= 20; i++) {
                try {
                    example.consume();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        producerThread.start();
        consumerThread.start();

        producerThread.join();
        consumerThread.join();
    }

    public synchronized void produce(int value) throws InterruptedException {
        while (queue.size() == MAX_SIZE) {
            wait();
        }
        queue.offer(value);
        System.out.println("生产者生产了:" + value);
        notifyAll();
    }

    public synchronized void consume() throws InterruptedException {
        while (queue.isEmpty()) {
            wait();
        }
        int value = queue.poll();
        System.out.println("消费者消费了:" + value);
        notifyAll();
    }
}

在上面的示例中,我们使用了 synchronized 关键字来实现线程同步。在 produce()consume() 方法中,每次都通过 synchronized 关键字来获取对象锁,以确保线程安全。同时,在队列满或队列空的情况下,我们使用了 wait() 方法来让当前线程进入等待状态,直到条件得到满足。

学习示例2:更高效的实现

在示例1中,我们使用了 synchronizedwait() 这些关键字来实现线程同步。但是,在高并发情况下,这些关键字会导致性能问题,因为每次获取锁和释放锁都会有一定的开销。因此,我们可以通过使用 java.util.concurrent 包中提供的并发工具来优化生产者消费者模型的实现。

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class ProducerConsumerExample2 {

    private BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
    private static final int MAX_SIZE = 10;

    public static void main(String[] args) throws InterruptedException {
        ProducerConsumerExample2 example = new ProducerConsumerExample2();

        Thread producerThread = new Thread(() -> {
            for (int i = 1; i <= 20; i++) {
                try {
                    example.produce(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread consumerThread = new Thread(() -> {
            for (int i = 1; i <= 20; i++) {
                try {
                    example.consume();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        producerThread.start();
        consumerThread.start();

        producerThread.join();
        consumerThread.join();
    }

    public void produce(int value) throws InterruptedException {
        queue.put(value);
        System.out.println("生产者生产了:" + value);
    }

    public void consume() throws InterruptedException {
        int value = queue.take();
        System.out.println("消费者消费了:" + value);
    }
}

在上面的示例中,我们使用了 java.util.concurrent 包中提供的 BlockingQueue 接口来实现线程同步。BlockingQueue 接口可以自动实现线程同步和阻塞队列的功能,从而简化了代码的实现。在生产者线程中,我们使用 put() 方法来向队列尾部添加元素;在消费者线程中,我们使用 take() 方法来从队列头部获取元素。在队列已满或队列为空的情况下,put()take() 方法会自动阻塞,直到条件得到满足。这样可以避免了使用 wait()notify() 导致的性能问题。

总结

生产者消费者模型是一种常用的线程同步模型,它通过在多个线程之间协调共享资源的访问,来提高系统的效率和可靠性。在示例1中,我们使用了 synchronizedwait() 这些关键字来实现线程同步;在示例2中,我们使用了 java.util.concurrent 包中提供的 BlockingQueue 接口来简化代码实现,并提高了程序的并发性能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JAVA生产者消费者(线程同步)代码学习示例 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • Java swing实现的计算器功能完整实例

    下面我将详细讲解如何实现“Java swing实现的计算器功能完整实例”。 简介 在介绍具体的实现方法之前,先简单介绍一下Java Swing。Swing是Java平台上的一组GUI(Graphical User Interface)构件库。它提供了一整套丰富的GUI构件,例如按钮、文本框、标签等。在Java中,通过将这些构件进行组合,就可以构建出各种各样的…

    Java 2023年5月19日
    00
  • SpringBoot集成JPA的示例代码

    下面我会详细讲解“SpringBoot集成JPA的示例代码”的完整攻略,过程中会包含两条示例。 1. 环境准备 在开始之前,我们需要确保我们的开发环境中已经安装好了以下软件: JDK 8或以上版本 IntelliJ IDEA或其他一款IDE 然后,我们需要确保我们在项目中引入了以下依赖: <dependency> <groupId>o…

    Java 2023年5月20日
    00
  • 一篇文章带你搞定JAVA Maven

    一篇文章带你搞定JAVA Maven 什么是Maven? Maven是一款基于Java平台的构建工具,它可以帮助开发者自动化地构建、打包、发布和管理Java项目中的各种依赖。使用Maven可以大大简化Java项目的开发和维护。Maven有一个中心仓库,里面包含了主流的Java依赖。我们可以通过Maven来自动从中心仓库中下载所需的依赖,避免了手动下载和管理依…

    Java 2023年5月19日
    00
  • java日志打印的完全使用指南

    Java日志打印的完全使用指南 为什么需要日志打印 在开发Java应用程序时,我们经常需要记录程序的运行状态,以便于调试、性能分析和错误排查。日志打印就是一种记录应用程序运行状态的方式,它可以用来记录各种类型的信息,如调试信息、异常信息、警告信息、错误信息等。 使用日志打印有以下几个好处: 记录程序的运行状态,便于排查问题。 通过日志分析来评估代码的性能表现…

    Java 2023年5月26日
    00
  • Java Web程序实现返回JSON字符串的方法总结

    下面就是针对“Java Web程序实现返回JSON字符串的方法总结”的完整攻略: 1.使用Jackson库 在Java Web程序中,可以使用Jackson库将Java对象转换为JSON字符串。使用Jackson库需要添加依赖,Maven中添加如下依赖: <dependency> <groupId>com.fasterxml.jack…

    Java 2023年5月26日
    00
  • Spring Boot环境属性占位符解析及类型转换详解

    Spring Boot环境属性占位符解析及类型转换详解 在Spring Boot应用程序中,我们可以使用环境属性占位符来引用应用程序的配置属性。环境属性占位符是以${}的形式出现的,其中包含了一个属性名,例如${server.port}。在本文中,我们将详细介绍Spring Boot环境属性占位符的解析和类型转换。 1. 环境属性占位符解析 Spring B…

    Java 2023年5月18日
    00
  • Spring入门到精通之注解开发详解

    《Spring入门到精通之注解开发详解》是一篇介绍Spring框架注解开发的文章。本文将对这篇文章进行详细讲解。 1. 引言 在Spring框架的开发中,注解已经成为了不可避免的话题。使用注解可以帮助开发者简化配置文件,提高代码的可读性和可维护性。 本篇文章将从基础知识讲起,逐渐深入,最终达到精通的程度。 2. 注解基础知识 2.1. 常见的注解 在Spri…

    Java 2023年5月19日
    00
  • Java反射机制详解

    Java反射机制详解 什么是Java反射 Java反射机制是指在程序运行过程中,通过获取对象的类信息,来操作改变对象的方法和属性。它能够使得程序在运行时才能得到要操作的类的相关信息,而不是在编写代码时就必须确定类的信息。Java反射机制主要由Java.lang.refect 包中的类和接口组成。 反射的优缺点 优点: 运行时动态地操作和处理类的属性和方法,增…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部