Java并发 | 单例的立即加载和延迟加载实现

单例模式

立即加载/饿汉模式

/**
 * 立即加载
 */
class MyObject {

    private static MyObject object = new MyObject();

    private MyObject() {
    }

    public static MyObject getInstance() {
        return object;
    }
}

class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }
}

public class Run {

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new MyThread());
            thread.start();
        }
    }
}

延迟加载/懒汉模式

第一版

存在不支持多线程问题

class MyObject {

    private volatile static MyObject object;

    private MyObject() {
    }

    public static MyObject getInstance() {
        try {
            if (Optional.ofNullable(object).isEmpty()) {
                // 模拟创建对象之前准备工作
                Thread.sleep(3000);
                object = new MyObject();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return object;
    }
}

第二版

方法加关键字synchronized,存在效率低问题

class MyObject {

    private volatile static MyObject object;

    private MyObject() {
    }

    synchronized public static MyObject getInstance() {
        try {
            if (Optional.ofNullable(object).isEmpty()) {
                // 模拟创建对象之前准备工作
                Thread.sleep(3000);
                object = new MyObject();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return object;
    }
}

第三版

针对某些重要的部分单独同步,存在不支持多线程问题

class MyObject {

    private volatile static MyObject object;

    private MyObject() {
    }

    public static MyObject getInstance() {
        try {
            if (Optional.ofNullable(object).isEmpty()) {
                // 模拟创建对象之前准备工作
                Thread.sleep(3000);
                synchronized (MyObject.class) {
                    object = new MyObject();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return object;
    }
}

最终版

使用DCL双检测锁机制

/**
 * 延迟加载
 */
class MyObject {

    private volatile static MyObject object;

    private MyObject() {
    }

    // 双检测机制
    public static MyObject getInstance() {
        try {
            if (Optional.ofNullable(object).isEmpty()) {
                // 模拟创建对象之前准备工作
                Thread.sleep(3000);
                synchronized (MyObject.class) {
                    if (Optional.ofNullable(object).isEmpty()) {
                        object = new MyObject();
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return object;
    }
}

class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println(MyObject.getInstance().hashCode());
    }
}

public class Run {

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new MyThread());
            thread.start();
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容