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

单例模式

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

主要特性:

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

实现方法

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 小时前
活动系统开发之采用设计模式与非设计模式的区别-后台功能总结
设计模式·php·tinkphp6
一头老羊10 小时前
前端常用的设计模式
设计模式
JOJO___10 小时前
Spring IoC 配置类 总结
java·后端·spring·java-ee
蜗牛学苑_武汉10 小时前
设计模式之代理模式
java·网络·java-ee·代理模式
严文文-Chris11 小时前
【设计模式-组合】
设计模式
Magnetic_h11 小时前
【iOS】单例模式
笔记·学习·ui·ios·单例模式·objective-c
kimloner12 小时前
工厂模式(二):工厂方法模式
java·设计模式·工厂方法模式
月临水12 小时前
JavaEE:网络编程(UDP)
java·网络·udp·java-ee
会发paper的学渣12 小时前
python 单例模式实现
开发语言·python·单例模式
kakwooi12 小时前
JavaEE---Spring IOC(2)
java·spring·java-ee