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日

相关文章

  • 详解Spring Data操作Redis数据库

    详解Spring Data操作Redis数据库 Redis是一种快速、开源的NoSQL数据库,它以键/值(key/value)存储数据,支持多种数据结构,包括字符串、哈希、列表、集合等。在应用程序开发中,连接Redis并进行数据操作是一个常见场景。Spring Data提供了对多种数据存储技术(包括Redis)的抽象和简化,同时还提供了常见的数据操作功能。下…

    Java 2023年5月20日
    00
  • SpringMVC框架实现图片上传与下载

    下面是关于“SpringMVC框架实现图片上传与下载”的完整攻略,包含两个示例说明。 SpringMVC框架实现图片上传与下载 SpringMVC是一个流行的Java Web框架,它可以帮助我们更加方便地构建Web应用程序。本文将介绍如何使用SpringMVC框架实现图片上传与下载。 步骤一:创建SpringMVC项目 首先,我们需要创建一个SpringMV…

    Java 2023年5月17日
    00
  • 新欢乐时光代码分析

    下面为您详细讲解“新欢乐时光代码分析”的完整攻略。 新欢乐时光代码分析完整攻略 什么是新欢乐时光 新欢乐时光是一款在线编程学习网站,提供基于计算机科学和编程方面的在线培训课程。它的使命是通过免费、灵活、高质量的教育资源,为全球的学生和教育者带来变革性的教育体验。 在线代码分析工具使用教程 新欢乐时光提供了一款在线代码分析工具,允许用户输入自己的代码,然后自动…

    Java 2023年6月15日
    00
  • Java8新特性时间日期库DateTime API及示例详解

    Java8新特性时间日期库DateTime API及示例详解 什么是DateTime API? DateTime API是Java 8引入的一个新功能,它提供了一组全新的日期和时间API,使得开发人员能够更轻松地操作日期和时间。同时,它还提供了处理时区、日历、持续时间等功能。 如何使用DateTime API? DateTime API包含在Java 8的j…

    Java 2023年5月20日
    00
  • SpringSecurity自定义登录界面

    在这里我将为您详细讲解SpringSecurity如何自定义登录界面的完整攻略。 1. SpringSecurity简介 SpringSecurity是一个基于Spring框架的安全管理框架,它提供了一套完整的安全控制方案,可以用于Web应用程序和企业级应用程序。 SpringSecurity包括认证(Authentication)、授权(Authoriza…

    Java 2023年5月20日
    00
  • Struts2和Ajax数据交互示例详解

    下面我将详细讲解“Struts2和Ajax数据交互示例详解”的完整攻略,包含以下几个部分: 概述:介绍本文的主要内容和目标。 环境配置:介绍Struts2和Ajax数据交互的环境配置。 示例1:使用Struts2和Ajax实现表单提交,并异步显示提交结果。 示例2:使用Struts2和Ajax实现无刷新分页查询。 1. 概述 本文将介绍如何实现 Struts…

    Java 2023年5月20日
    00
  • Bootstrap和Java分页实例第一篇

    首先,该攻略主要针对的是Bootstrap和Java分页实例的基础入门教程,对于前端和Java开发初学者非常实用。文本将分为以下几个部分进行讲解: 一、Bootstrap的基础使用 1.1 引入Bootstrap到项目中 在使用Bootstrap进行开发时,首先需要在项目中引入Bootstrap的CSS和JS文件,这可以通过CDN链接或者下载本地文件的方式引…

    Java 2023年6月15日
    00
  • Spring Cloud下实现用户鉴权的方案

    下面我将为大家详细讲解“Spring Cloud下实现用户鉴权的方案”的完整攻略。本攻略分为以下几个部分: Spring Cloud微服务架构 鉴权的基本概念 用户鉴权的实现方案 示例一:使用JWT实现用户鉴权 示例二:使用OAuth2实现用户鉴权 1. Spring Cloud微服务架构 Spring Cloud是基于Spring Boot的微服务开发框架…

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