关于java (懒汉)单例模式是否存在线程安全的问题

场景:
        曾经学习设计模式中单例模式,发现自己平时对于这种模式应用还是很多的,网上一直有人说 懒汉式的单例模式存在线程安全问题,我不太相信所以自己做了个测试代码,啥都不说了,直接上测试代码和结果

[TestApp.java]
package test.singleton;

/**
 * Author: skyline{http://my.oschina.net/skyline520}
 * Created: 13-5-11 下午6:14
 */
public class TestApp {

    private int client_num  = 10000;

    public void start(){
        long start = System.currentTimeMillis();
        for(int i=0;i<client_num;i++){
            LoadSingletonThread thread = new LoadSingletonThread();
            try {
                ThreadPools.daemonThreadPool().execute(thread);
            } catch (Exception e) {
                e.printStackTrace();
                //处理拒绝提交后问题
            }
        }
        long end = System.currentTimeMillis();
        System.out.println(SingletonCollection.concurrentHashMap);
        System.out.println("用时["+(end-start)+"]ms");
    }

    public static void main(String[] args) {
        TestApp testApp = new TestApp();
        testApp.start();
    }
}
[LoadSingletonThread.java]
package test.singleton;


import org.apache.log4j.Logger;


/**
 * Author: skyline{http://my.oschina.net/skyline520}
 * Created: 13-5-11 下午6:07
 */
public class LoadSingletonThread implements Runnable {


    private static final Logger logger = Logger.getLogger(LoadSingletonThread.class);
    @Override
    public void run() {
        logger.info("开始获取实体类......");
        LazySingleton lazySingleton = LazySingleton.getInstance();
//        EagerSingleton lazySingleton = EagerSingleton.getInstance();
        SingletonCollection.concurrentHashMap.put(lazySingleton.toString(),lazySingleton);
    }
}
[LazySingleton.java]
package test.singleton;

import org.apache.log4j.Logger;

/**
 * Author: skyline{http://my.oschina.net/skyline520}
 * Created: 13-5-11 下午6:04
 */
public class LazySingleton {

    private static final Logger logger = Logger.getLogger(LazySingleton.class);

    private static LazySingleton lazySingleton = null;

    private LazySingleton(){
         logger.info("LazySingleton 实例创建......");
    }

    public  static LazySingleton getInstance(){
        if(lazySingleton == null){
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }

}
[SingletonCollection.java]
package test.singleton;

import org.apache.log4j.Logger;

import java.util.concurrent.ConcurrentHashMap;

/**
 * Author: skyline{http://my.oschina.net/skyline520}
 * Created: 13-5-11 下午6:09
 */
public class SingletonCollection {

    private static final Logger logger = Logger.getLogger(SingletonCollection.class);

    //用来存放得到的单例类实例集合
    public static ConcurrentHashMap<String,Object> concurrentHashMap = new ConcurrentHashMap<String,Object>();
}
[ThreadPools.java]
package test.singleton;

import org.apache.log4j.Logger;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Author: skyline{http://my.oschina.net/skyline520}
 * Created: 13-5-11 下午5:57
 */
public class ThreadPools {
    private static final Logger logger = Logger.getLogger(ThreadPools.class);

    private static ThreadPoolExecutor daemonPool = null; //固定线程池

    public synchronized static ThreadPoolExecutor daemonThreadPool(){
        if(daemonPool == null){
            logger.info("固定线程池启动......");
            daemonPool = new ThreadPoolExecutor(100,200,10, TimeUnit.SECONDS,
                    new ArrayBlockingQueue<Runnable>(100),
                    new ThreadPoolExecutor.AbortPolicy());
        }
        return daemonPool;
    }
}
测试结果: 
会出现获取两个单例类的问题
关于java (懒汉)单例模式是否存在线程安全的问题_第1张图片

修改: 把单例类中 getInstance 方法 加上 synchronized 关键字后,则不会出现上述问题
修改后结果:
关于java (懒汉)单例模式是否存在线程安全的问题_第2张图片

你可能感兴趣的:(java,单例,线程安全)