【设计模式】单例模式和生产者消费者模型

2024-08-24 22:52

本文主要是介绍【设计模式】单例模式和生产者消费者模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

单例模式

单例模式是一种常见的设计模式,旨在确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于需要控制资源的类,比如配置管理、线程池等。

主要特性:

  • 唯一性:类只有一个实例。
  • 全局访问:提供一个静态方法获取该实例。
  • 延迟加载(可选):实例在第一次使用时创建。

实现方法

1. 饿汉式单例

在类加载时就创建实例,线程安全,但不支持延迟加载。

public class Singleton {// 静态实例private static final Singleton instance = new Singleton();// 私有构造函数private Singleton() {}// 公共方法获取实例public static Singleton getInstance() {return instance;}
}

2. 懒汉式单例

在第一次调用时创建实例,支持延迟加载,线程不安全的实现。

public class Singleton {// 静态实例private static Singleton instance;// 私有构造函数private Singleton() {}// 公共方法获取实例public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

3. 线程安全的懒汉式单例

通过同步方法实现线程安全。

public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

4. 双重检查锁定

结合懒加载和性能优化,通过“双重检查”实现线程安全,减少同步开销。

public class Singleton {private static volatile Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) { // 第一次检查synchronized (Singleton.class) {if (instance == null) { // 第二次检查instance = new Singleton();}}}return instance;}
}

总结

单例模式通过限制实例化数量,简化了代码管理和资源控制。在选择实现方式时,要考虑到线程安全和性能需求,适当选择实现。

wait 和 notify 方法

在Java中,wait 和 notify 是用于线程间通信的重要方法。这些方法被定义在 Object 类中,因此所有的对象都可以利用这些方法进行线程协调。它们通常用于同步块(synchronized block)中,以实现线程的等待和通知机制。

wait 方法

wait() 方法使当前线程等待,直到其他线程调用 notify() 或 notifyAll() 方法来唤醒它。调用 wait() 方法的线程会释放持有的对象锁。

notify 方法

notify() 方法用于唤醒一个正在等待该对象监视器的线程。如果有多个线程在等待,则其中一个线程会被唤醒,具体被哪个线程唤醒是不确定的。使用 notifyAll() 可以唤醒所有在等待该对象监视器的线程。

生产者消费者模型

生产者消费者模型是一种常见的并发设计模式,它用于解决生产者和消费者之间的协作问题。生产者负责生成数据,消费者则负责处理数据。这个模型通过缓冲区的方式进行协调,确保生产者在缓冲区满时暂停生产,消费者在缓冲区空时暂停消费。

主要特性:

  1. 并发性:生产者和消费者可以并行工作。
  2. 缓冲区:使用一个共享的缓冲区来存储数据。
  3. 同步控制:需要通过适当的同步机制来确保线程安全。

实现方法

以下是一个使用 Java 的生产者消费者模型的示例,利用 wait() 和 notify() 方法进行线程间的通信。

1. 定义缓冲区

import java.util.LinkedList;class Buffer {private LinkedList<Integer> queue = new LinkedList<>();private final int CAPACITY = 5;// 生产者向缓冲区添加数据public synchronized void produce(int value) throws InterruptedException {while (queue.size() == CAPACITY) {wait(); // 如果缓冲区满,等待消费者消费}queue.add(value);System.out.println("Produced: " + value);notifyAll(); // 通知消费者可以消费}// 消费者从缓冲区获取数据public synchronized int consume() throws InterruptedException {while (queue.isEmpty()) {wait(); // 如果缓冲区空,等待生产者生产}int value = queue.removeFirst();System.out.println("Consumed: " + value);notifyAll(); // 通知生产者可以生产return value;}
}

2. 定义生产者

class Producer extends Thread {private Buffer buffer;public Producer(Buffer buffer) {this.buffer = buffer;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {try {buffer.produce(i);Thread.sleep(500); // 模拟生产时间} catch (InterruptedException e) {e.printStackTrace();}}}
}

3. 定义消费者

class Consumer extends Thread {private Buffer buffer;public Consumer(Buffer buffer) {this.buffer = buffer;}@Overridepublic void run() {for (int i = 0; i < 10; i++) {try {buffer.consume();Thread.sleep(1000); // 模拟消费时间} catch (InterruptedException e) {e.printStackTrace();}}}
}

4. 测试生产者和消费者

public class ProducerConsumerExample {public static void main(String[] args) {Buffer buffer = new Buffer();Producer producer = new Producer(buffer);Consumer consumer = new Consumer(buffer);producer.start();consumer.start();}
}

总结

在这个示例中,生产者和消费者通过一个共享的缓冲区进行交互,使用 synchronized 关键字、wait() 和 notifyAll() 方法实现同步控制。生产者在缓冲区满时暂停生产,消费者在缓冲区空时暂停消费,从而有效地协调了两者之间的关系。这个模型广泛应用于多线程编程、任务调度等场景。

这篇关于【设计模式】单例模式和生产者消费者模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1103839

相关文章

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

C#原型模式之如何通过克隆对象来优化创建过程

《C#原型模式之如何通过克隆对象来优化创建过程》原型模式是一种创建型设计模式,通过克隆现有对象来创建新对象,避免重复的创建成本和复杂的初始化过程,它适用于对象创建过程复杂、需要大量相似对象或避免重复初... 目录什么是原型模式?原型模式的工作原理C#中如何实现原型模式?1. 定义原型接口2. 实现原型接口3

大数据spark3.5安装部署之local模式详解

《大数据spark3.5安装部署之local模式详解》本文介绍了如何在本地模式下安装和配置Spark,并展示了如何使用SparkShell进行基本的数据处理操作,同时,还介绍了如何通过Spark-su... 目录下载上传解压配置jdk解压配置环境变量启动查看交互操作命令行提交应用spark,一个数据处理框架

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo

springboot rocketmq配置生产者和消息者的步骤

《springbootrocketmq配置生产者和消息者的步骤》本文介绍了如何在SpringBoot中集成RocketMQ,包括添加依赖、配置application.yml、创建生产者和消费者,并展... 目录1. 添加依赖2. 配置application.yml3. 创建生产者4. 创建消费者5. 使用在

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll