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

单例模式

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

主要特性:

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

实现方法

1. 饿汉式单例

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

java 复制代码
public class Singleton {
    // 静态实例
    private static final Singleton instance = new Singleton();

    // 私有构造函数
    private Singleton() {}

    // 公共方法获取实例
    public static Singleton getInstance() {
        return instance;
    }
}

2. 懒汉式单例

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

java 复制代码
public class Singleton {
    // 静态实例
    private static Singleton instance;

    // 私有构造函数
    private Singleton() {}

    // 公共方法获取实例
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

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

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

java 复制代码
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

4. 双重检查锁定

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

java 复制代码
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中,waitnotify 是用于线程间通信的重要方法。这些方法被定义在 Object 类中,因此所有的对象都可以利用这些方法进行线程协调。它们通常用于同步块(synchronized block)中,以实现线程的等待和通知机制。

wait 方法

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

notify 方法

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

生产者消费者模型

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

主要特性:

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

实现方法

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

1. 定义缓冲区

java 复制代码
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. 定义生产者

java 复制代码
class Producer extends Thread {
    private Buffer buffer;

    public Producer(Buffer buffer) {
        this.buffer = buffer;
    }

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

3. 定义消费者

java 复制代码
class Consumer extends Thread {
    private Buffer buffer;

    public Consumer(Buffer buffer) {
        this.buffer = buffer;
    }

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

4. 测试生产者和消费者

java 复制代码
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() 方法实现同步控制。生产者在缓冲区满时暂停生产,消费者在缓冲区空时暂停消费,从而有效地协调了两者之间的关系。这个模型广泛应用于多线程编程、任务调度等场景。

相关推荐
思忖小下9 小时前
梳理你的思路(从OOP到架构设计)_简介设计模式
设计模式·架构·eit
天使day11 小时前
SpringMVC
java·spring·java-ee
liyinuo201711 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
寻找沙漠的人12 小时前
理解JVM
java·jvm·java-ee
寻找沙漠的人13 小时前
JavaEE 导读与环境配置
java·spring boot·java-ee
aaasssdddd9613 小时前
C++的封装(十四):《设计模式》这本书
数据结构·c++·设计模式
T1an-113 小时前
设计模式之【观察者模式】
观察者模式·设计模式
思忖小下15 小时前
梳理你的思路(从OOP到架构设计)_设计模式Factory Method模式
设计模式·工厂方法模式·eit
霁月风16 小时前
设计模式——工厂方法模式
c++·设计模式·工厂方法模式