Java编程生产者消费者实现的四种方法

Java编程生产者消费者实现的四种方法

生产者消费者问题是指在生产者和消费者之间同步的问题。生产者一直在生产消息,消费者一直在从队列中取走消息,并且队列中只能存储有限的消息。Java中提供了多种实现生产者消费者问题的方法,具体如下:

方法一:使用wait()和notify()方法

这是最基本的一种实现方式。使用wait()方法让生产者线程等待,当消息队列满时,调用notify()方法,让消费者线程去消费消息。反之,当队列为空时,调用wait()方法,让生产者线程去产生消息。下面是一个简单的示例:

class MessageQueue {
    private int[] queue = new int[10];
    private int front = 0, rear = 0, size = 0;

    public synchronized void write(int num) throws InterruptedException {
        while (size == queue.length) {
            wait();
        }
        queue[rear] = num;
        rear = (rear + 1) % queue.length;
        size++;
        notifyAll();
    }

    public synchronized int read() throws InterruptedException {
        while (size == 0) {
            wait();
        }
        int num = queue[front];
        front = (front + 1) % queue.length;
        size--;
        notifyAll();
        return num;
    }
}

class Producer extends Thread {
    private MessageQueue queue;

    public Producer(MessageQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                Thread.sleep(1000);
                System.out.println("put " + i + " into queue.");
                queue.write(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Consumer extends Thread {
    private MessageQueue queue;

    public Consumer(MessageQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                int num = queue.read();
                System.out.println("get " + num + " from queue.");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class WaitNotifyDemo {
    public static void main(String[] args) throws InterruptedException {
        MessageQueue queue = new MessageQueue();
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
    }
}

方法二:使用Lock和Condition

使用Lock和Condition可以实现更为灵活和安全的线程同步。Condition的await()方法和signal()方法就相当于wait()和notify()方法,但是Condition比wait、notify更加安全可靠。示例代码如下:

class MessageQueue {
    private int[] queue = new int[10];
    private int front = 0, rear = 0, size = 0;
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public void write(int num) throws InterruptedException {
        lock.lock();
        try {
            while (size == queue.length) {
                notFull.await();
            }
            queue[rear] = num;
            rear = (rear + 1) % queue.length;
            size++;
            notEmpty.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public int read() throws InterruptedException {
        lock.lock();
        try {
            while (size == 0) {
                notEmpty.await();
            }
            int num = queue[front];
            front = (front + 1) % queue.length;
            size--;
            notFull.signalAll();
            return num;
        } finally {
            lock.unlock();
        }
    }
}

class Producer extends Thread {
    private MessageQueue queue;

    public Producer(MessageQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                Thread.sleep(1000);
                System.out.println("put " + i + " into queue.");
                queue.write(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Consumer extends Thread {
    private MessageQueue queue;

    public Consumer(MessageQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                int num = queue.read();
                System.out.println("get " + num + " from queue.");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class LockConditionDemo {
    public static void main(String[] args) throws InterruptedException {
        MessageQueue queue = new MessageQueue();
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
    }
}

方法三:使用BlockingQueue

Java中提供了BlockingQueue接口可以很方便的实现生产者消费者队列。BlockingQueue常用的实现类有ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。示例代码如下:

class Producer extends Thread {
    private BlockingQueue<Integer> queue;

    public Producer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                Thread.sleep(1000);
                System.out.println("put " + i + " into queue.");
                queue.put(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Consumer extends Thread {
    private BlockingQueue<Integer> queue;

    public Consumer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                int num = queue.take();
                System.out.println("get " + num + " from queue.");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class BlockingQueueDemo {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
    }
}

方法四:使用Semaphore

使用Semaphore也可以实现生产者消费者问题,但是需要通过计数器来控制生产者和消费者的线程数。当计数器为0时,消费者线程需要等待;当计数器达到阈值时,生产者线程需要等待。具体示例代码如下:

class MessageQueue {
    private int[] queue = new int[10];
    private int front = 0, rear = 0, size = 0;
    private Semaphore notFull = new Semaphore(10);
    private Semaphore notEmpty = new Semaphore(0);

    public void write(int num) throws InterruptedException {
        notFull.acquire();
        queue[rear] = num;
        rear = (rear + 1) % queue.length;
        size++;
        notEmpty.release();
    }

    public int read() throws InterruptedException {
        notEmpty.acquire();
        int num = queue[front];
        front = (front + 1) % queue.length;
        size--;
        notFull.release();
        return num;
    }
}

class Producer extends Thread {
    private MessageQueue queue;

    public Producer(MessageQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                Thread.sleep(1000);
                System.out.println("put " + i + " into queue.");
                queue.write(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Consumer extends Thread {
    private MessageQueue queue;

    public Consumer(MessageQueue queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                int num = queue.read();
                System.out.println("get " + num + " from queue.");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class SemaphoreDemo {
    public static void main(String[] args) throws InterruptedException {
        MessageQueue queue = new MessageQueue();
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
    }
}

以上是Java编程生产者消费者实现的四种方法的详细攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java编程生产者消费者实现的四种方法 - Python技术站

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

相关文章

  • tomcat简介_动力节点Java学院整理

    Tomcat简介 Tomcat是一种开源的Servlet容器和JSP引擎,它使得Java代码可以在Web服务器上运行,可以用于纯Java的Web开发。以下是动力节点Java学院整理的一份Tomcat简介攻略。 安装 首先,我们需要在官网上下载对应的Tomcat版本,并解压缩到指定的目录。 配置 Tomcat的主要配置文件是conf文件夹中的server.xm…

    Java 2023年6月2日
    00
  • java输入空行结束问题

    Java输入空行结束问题是指,当我们从键盘输入多行数据时,如何用一个空行来结束输入。这个问题在编写需要从键盘输入数据的Java程序中经常会用到。下面就是一个完整的攻略: 1. 使用Scanner类的nextLine方法 Scanner类是Java中常用的一个从键盘读取输入数据的工具类。我们可以使用Scanner类的nextLine方法来读取一行输入,并判断输…

    Java 2023年5月27日
    00
  • 微信公众平台获取access_token的方法步骤

    下面是关于微信公众平台获取access_token的方法步骤以及示例说明的完整攻略。 什么是access_token? 在微信公众平台开发中,为了保证安全性,许多接口需要access_token,access_token是认证微信公众账号的全局唯一票据,用于调用微信公众平台开发接口。 获取access_token的方法步骤 准备请求参数 请求参数是指appi…

    Java 2023年5月23日
    00
  • Spring Boot 整合JPA 数据模型关联使用操作(一对一、一对多、多对多)

    下面是“Spring Boot 整合 JPA 数据模型关联使用操作(一对一、一对多、多对多)”的完整攻略。 简介 在讲解具体的操作步骤之前,我们需要先了解一些基础知识。 JPA JPA,全称为 Java Persistence API,即 Java 持久化 API,是 Java EE 技术的一部分,是一种轻量级的 Java ORM 框架,主要是作为 Hibe…

    Java 2023年5月20日
    00
  • IDEA2022创建Maven Web项目教程(图文)

    以下是“IDEA2022创建Maven Web项目教程(图文)”的完整攻略: IDEA2022创建Maven Web项目教程(图文) 在开始之前,请确保你已经安装了Maven和IntelliJ IDEA 2022。 步骤一:创建Maven Web项目 打开IntelliJ IDEA,点击“File”菜单,选择“New” – “Project ”。 在弹出的窗…

    Java 2023年6月2日
    00
  • 2022版IDEA创建一个maven项目的超详细图文教程

    下面我将为您详细讲解如何在2022版IDEA中创建一个maven项目的超详细图文教程。 步骤一:打开IDEA并创建一个新项目 打开2022版的IDEA,选择”Create New Project”(新建项目)。 在弹出窗口中,选择”Maven”项目类型,并点击”Next”。 在下一个窗口中选择”Maven Quickstart Archetype”原型(注意…

    Java 2023年5月20日
    00
  • Springboot集成restTemplate过程详解

    下面是详细讲解“Springboot集成restTemplate过程详解”的完整攻略。 介绍 在Springboot中,restTemplate是一个常用的HTTP客户端,用于发送REST请求和接收REST响应。本文将介绍如何在Springboot中集成restTemplate。 步骤 步骤1:添加依赖 首先,在项目的pom.xml文件中添加以下依赖: &l…

    Java 2023年5月15日
    00
  • Java内省实例解析

    Java内省实例解析 什么是Java内省? Java内省是指通过类提供的公共方法来访问类属性和方法的一种机制,用于实现Java Bean自省功能。 如何使用Java内省? Java内省通过Java自带的Introspector类实现。Introspector类提供了丰富的API,用于获取和操作Java Bean中的属性、方法等。 获取Java Bean信息 …

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