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

单例模式

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

主要特性:

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

实现方法

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

相关推荐
哪 吒7 小时前
最简单的设计模式,抽象工厂模式,是否属于过度设计?
设计模式·抽象工厂模式
Theodore_10227 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
转世成为计算机大神10 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
小乖兽技术11 小时前
23种设计模式速记法
设计模式
小白不太白95012 小时前
设计模式之 外观模式
microsoft·设计模式·外观模式
小白不太白95012 小时前
设计模式之 原型模式
设计模式·原型模式
澄澈i12 小时前
设计模式学习[8]---原型模式
学习·设计模式·原型模式
小白不太白95019 小时前
设计模式之建造者模式
java·设计模式·建造者模式
孟秋与你21 小时前
【spring】spring单例模式与锁对象作用域的分析
java·spring·单例模式
菜菜-plus21 小时前
java 设计模式 模板方法模式
java·设计模式·模板方法模式