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日

相关文章

  • java基于jcifs.smb实现远程发送文件到服务器

    下面是关于“Java基于jcifs.smb实现远程发送文件到服务器”的完整攻略。 概述 jcifs.smb是一个java实现的SMB网络协议库,可以在java应用程序中实现与SMB服务器的连接。通过这个库,我们可以在java中实现与文件共享服务器之间的文件传输。在接下来的攻略中,我将详细介绍如何使用jcifs.smb库实现远程发送文件到服务器。 步骤一:引入…

    Java 2023年5月20日
    00
  • java递归菜单树转换成pojo对象

    下面我将详细讲解“Java递归菜单树转换成POJO对象”的完整攻略。 什么是递归菜单树? 递归菜单树是一种常见的数据结构,它可以用来表示树形结构的数据,例如网站的导航菜单、商品分类等。一个递归菜单树通常由多个节点组成,每个节点可以包含一个或多个子节点,因此它具有递归的特性。 在Java编程中,我们通常使用多个Java对象来表示一个递归菜单树,其中每个Java…

    Java 2023年5月26日
    00
  • Java经典面试题最全汇总208道(一)

    Java经典面试题最全汇总208道(一)是一篇非常详细的关于Java面试题的攻略文档。本文共分为以下几个部分: Java基础 集合 多线程 JVM Spring 设计模式 网络编程 数据库 每个部分都细致的从概念到实例进行了详细的说明。下面将对每个部分进行简要的介绍。 Java基础 Java基础部分主要介绍了Java的概念、特性、数据类型等。还包括了关于对象…

    Java 2023年5月23日
    00
  • SpringBoot3集成SLF4J+logback进行日志记录的实现

    下面就为大家讲解一下“SpringBoot3集成SLF4J+logback进行日志记录的实现”的完整攻略。 1. 引入相关依赖 在SpringBoot的pom.xml文件中添加SLF4J和logback的依赖: <dependency> <groupId>org.springframework.boot</groupId>…

    Java 2023年5月26日
    00
  • Java中的Spring Security配置过滤器

    下面是关于Java中的Spring Security配置过滤器的完整攻略: 概述 Spring Security是一个基于Spring框架的安全性管理框架,通过Spring Security可以实现对系统资源的保护。在Spring Security中,Filter链是一个非常重要的组件。Spring Security通过Filter实现了对Web请求的控制。…

    Java 2023年6月3日
    00
  • Java8 Lambda表达式详解及实例

    Java8 Lambda表达式详解及实例 什么是Lambda表达式 Lambda表达式是Java8中引入的一个新特性,是一种轻量级的匿名函数,用来替代过往繁琐的匿名内部类编写方式。Lambda表达式可以被赋值到一个变量中,或者传递到一个方法中作为参数,像对象一样使用。Lambda表达式的语法简洁、优雅,让Java8代码的可读性和可维护性更加强大。 Lambd…

    Java 2023年5月26日
    00
  • idea运行main方法或Test避免编译整个应用的实现方法

    要想在 IDEA 中运行 main 方法或 Test 时避免编译整个应用程序,可以使用以下两种方法: 方法一:使用 JUnit Platform 使用 JUnit Platform 可以大幅度提高测试运行速度。JUnit Platform 是一个简单易用的测试框架,它运行在单独的进程中,可以在测试时避免编译整个应用程序。 以下是使用 JUnit Platfo…

    Java 2023年5月26日
    00
  • Maven打包并生成运行脚本的示例代码

    这里是Maven打包并生成运行脚本的完整攻略,包含两个示例代码。 1. Maven打包过程 在使用Maven进行打包之前,需要在项目的pom.xml文件中添加以下插件: <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupI…

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