zoukankan      html  css  js  c++  java
  • 【java基础领域】就单例模式谈并发问题

    单例模式旨在创建一个唯一的对象,一种恶汉式 一种懒汉式。没什么好说的。但是,在多线程下的情景下 就会出现问题

    1、单例模式之恶汉式

    /**
     * @author i
     * @create 2019/9/18 20:45
     * @Description 恶汉式
     */
    public class Singleton {
    
        private static Singleton singleton = new Singleton();
    
        //私有化构造方法
        private Singleton(){
    
        }
    
        public static Singleton getInstance(){
            return singleton;
        }
    }

    1.2、多线程下使用恶汉式创建对象

    public static void main(String[] args) {
            ExecutorService threadPool = Executors.newFixedThreadPool(20);
            for (int i = 0; i < 20 ; i++) {
                threadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+" "+Singleton.getInstance());
                    }
                });
            }
        }

    1.3、结果:从结果中可以看到 我们使用恶汉式多线程下创建对象是没有问题的。因此 就可以下结论 恶汉式情况下 并发使用不会出现问题, 

    2、单例模式之懒汉式

    package com.hblg.t1;
    
    /**
     * @author i
     * @create 2019/9/18 20:48
     * @Description 懒汉式单例实现
     */
    public class Singleton2 {
    
        private static Singleton2 instance = null;
    
        public Singleton2(){
    
        }
    
        /***
         * 
         * @return
         */
        public static  Singleton2 getInstance(){
            if(instance == null){
                instance = new Singleton2();   
            }
            return instance;
        }
    
    
    }
    

    2.1 多线程下使用懒汉式创建对象

    ExecutorService threadPool = Executors.newFixedThreadPool(20);
            for (int i = 0; i < 10; i++) {
                threadPool.execute(new Runnable() {
    
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+" "+Singleton2.getInstance());
                    }
                });
            }
    
            threadPool.shutdown();

    2.3 结果 分析 我们可以知道,通过多线程懒汉式创建单例出现了问题,原因是什么呢。

    if(instance == null){
        instance = new Singleton2();
    }
    return instance;

    原因就在于此,那就是当多个线程去调用getInstance()方法,由于上面的3行语句 不具有原子性操作,当t1线程进入 第一行

    这个时候。线程t2 抢占了cpu执行权获取到了cpu执行时间,去判断时候为空 就会自行创建一个对象。

    所有 我们可以通过加锁的方式 来保证数据一致性问题。

    /***
         * 双重检测加锁
         * @return
         */
        public static synchronized Singleton2 getInstance(){
            if(instance == null){
                synchronized (Singleton2.class){
                    if(instance == null){
                        instance = new Singleton2();   //指令重排序  加vloatile关键字
                    }
                }
            }
            return instance;
        }

    通过上面 可以解决。

  • 相关阅读:
    Linux命令应用大词典-第11章 Shell编程
    Kubernetes 学习12 kubernetes 存储卷
    linux dd命令
    Kubernetes 学习11 kubernetes ingress及ingress controller
    Kubernetes 学习10 Service资源
    Kubernetes 学习9 Pod控制器
    Kubernetes 学习8 Pod控制器
    Kubernetes 学习7 Pod控制器应用进阶2
    Kubernetes 学习6 Pod控制器应用进阶
    Kubernetes 学习5 kubernetes资源清单定义入门
  • 原文地址:https://www.cnblogs.com/qxlxi/p/12860814.html
Copyright © 2011-2022 走看看