JavaEE初阶 多线程:单例模式 | 阻塞队列

Singleton 单例模式

单例模式能保证某个类在程序中只存在唯⼀⼀份实例,⽽不会创建出多个实例。

单例模式最常⻅的实现⽅的是"饿汉"和"懒汉"两种

饿汉模式,运行即创建

java 复制代码
class Singleton{
    private static Singleton instance=new Singleton();
    private static Singleton getinstance(){
        return instance;
    }
    //构造方法私有化,仅限在Singleton类中实例化,确保单例化
    private  Singleton(){
    }
}

懒汉模式,需要时再创建

java 复制代码
class Singleton{
    private static Object locker=new Object();
//volatile修饰instance
    private static volatile Singleton instance=null;
    public static Singleton getinstance(){
if (instance==null){
    synchronized (locker){
        if (instance==null){
            instance=new Singleton();
        }
    }
}
        //实例化时原子操作
        return instance;
    }
    //构造方法私有化,仅限在Singleton类中实例化,确保单例化
    private  Singleton(){
    }
}

饿汉模式不存在线程安全问题,懒汉模式当多个线程调用getInstance⽅法,就可能导致创建 出多个实例,后面的实例会覆盖前面实例,资源浪费。

⼀旦实例已经创建好了,后⾯再多线程环境调⽤getInstance就不再有线程安全问题了(不再修改 instance 了)

使用锁保证原子性

java 复制代码
//判断是否需要加锁,已经创建实例后减少资源浪费
if (instance==null){
    synchronized (locker){
//判断是否需要实例化
        if (instance==null){
            instance=new Singleton();
        }
    }
}

但线程在加锁操作时仍会被调度,导致t1线程中instance使用了未初始化的实例,因此需要加入volatile避免重排序

java 复制代码
class DBUtil {
    private static volatile DataSource dataSource = null;

    public static DataSource getInstance() {
        if (dataSource == null) {
            synchronized (DBUtil.class) {
                if (dataSource == null) {
                    MysqlDataSource ds = new MysqlDataSource();
                    ds.setUrl("jdbc:mysql://127.0.0.1:3306/java117?characterEncoding=utf8&useSSL=false");
                    ds.setUser("root");
                    ds.setPassword("2222");
                    dataSource = ds;
                }
            }
        }
        return dataSource;
    }
   private DBUtil{}
}

阻塞队列

阻塞队列是⼀种特殊的队列.也遵守"先进先出"的原则,具有线程安全的阻塞队列

1.当队列满的时候,继续⼊队列就会阻塞,直到有其他线程从队列中取⾛元素.

2.当队列空的时候,继续出队列也会阻塞,直到有其他线程往队列中插⼊元素.

阻塞的队列的应用场景:生产消费者模型

阻塞队列的使用

在Java标准库中内置了阻塞队列.如果我们需要在⼀些程序中使⽤阻塞队列,直接使⽤标准库中的即 可.

1.BlockingQueue是⼀个接⼝.真正实现类包括LinkedBlockingQueue/ArrayBlockingQueue/PriorityBlockingQueue.

2.put⽅法 ⽤于阻塞式的⼊队列,take⽤于阻塞式的出队列.

3.BlockingQueue也有offer,poll,peek等⽅法,但是这些⽅法不带有阻塞特性

相关推荐
智慧物业老杨15 小时前
物业数字化落地思考:真正的转型,是底层数据秩序的重构
java·大数据·人工智能·微服务·系统架构
星空18 小时前
金蝶苍穹build.gradle配置
java·build.gradle
C++ 老炮儿的技术栈19 小时前
我们在设计tcp协议时,要传一个字符串过去,报文:头十长度十内容,是否要把‘\0‘也填入,长度是否包含‘\0‘
开发语言·数据结构·c++·mfc·c
传奇开心果编程20 小时前
【Rust入门练中学】第2课:变量、可变性与常量
开发语言·学习·rust
zr想努力20 小时前
从0开始配置Perforce4环境
开发语言
步行cgn21 小时前
Spring 基于 XML 的自动装配:byName 详解
java·后端·spring
大帅点兵21 小时前
Apache Ant 1.9.9 完整讲解
java
幸运小圣21 小时前
PointerEvent 常用属性与事件整理【JavaScript】
开发语言·javascript·ecmascript
LuTshoes21 小时前
spring ai 实战 手搓 PlaneExecuteAgent
java·人工智能·spring·ai
这料鬼有毒1 天前
二刷hot100-73.矩阵置零
java