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;
        }

    通过上面 可以解决。

  • 相关阅读:
    BI之SSAS完整实战教程1 -- 开篇, BI简介 & SSAS简介
    MVC 5 + EF6 入门完整教程14 -- 动态生成面包屑导航
    MVC5+EF6 入门完整教程12--灵活控制Action权限
    JVM垃圾收集
    JVM类加载
    前端UI框架
    前端学习
    JVM字节码
    网络编程
    Java NIO
  • 原文地址:https://www.cnblogs.com/qxlxi/p/12860814.html
Copyright © 2011-2022 走看看