如何实现Singleton模式
如何实现Singleton模式,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
我们提供的服务有:网站设计制作、网站设计、微信公众号开发、网站优化、网站认证、博乐ssl等。为成百上千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的博乐网站制作公司
题目
设计一个类,我们只能生成该类的一个实例
分析
最简单实现
私有构造方法
静态方法获取实例
是否需要考虑内存或并发环境
如果需要考虑内存,使用到时才创建实例对象(饿汉),不使用时就不创建实例(懒汉,懒加载)。
如果需要考虑线程安全,就要确保获取实例是同步的,避免创建多个实例。
实现方式
[x] 1. 单线程(懒汉式、饿汉式)
[x] 2. 多线程工作效率不高(加锁获取实例的方法)
[x] 3. 加同步锁前后两次判断实例是否已存在
[x] 4. 利用静态初始化创建实例(推荐,线程安全,会占用一部分内存)
[x] 5. 利用静态内部类实现按需创建实例(最推荐,线程安全,效率高,聪明的你应该可以明白的)
编码实现
1. 单线程(懒汉式、饿汉式)
饿汉单例
package cn.jast.java.offer.singleton; /** * 简单饿汉单例 * */ public class SimpleHungerSingleton { private static SimpleHungerSingleton simpleSingleton; private SimpleHungerSingleton(){ simpleSingleton = new SimpleHungerSingleton(); } public static SimpleHungerSingleton getInstance(){ return simpleSingleton; } }
简单懒汉单例
package cn.jast.java.offer.singleton; /** * 简单懒汉单例 * */ public class SimpleLazySingleton { private static SimpleLazySingleton simpleSingleton; private SimpleLazySingleton(){ } public static SimpleLazySingleton getInstance(){ if(simpleSingleton == null){ simpleSingleton = new SimpleLazySingleton(); } return simpleSingleton; } }
线程安全测试
/** * 测试简单单例的线程安全 */ public static void testSimpleLazySingleton(){ SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ SimpleLazySingleton simpleLazySingleton = SimpleLazySingleton.getInstance(); singletonSet.add(simpleLazySingleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } }
输出:
简单单例存在创建多个实例对象,实例如下: [cn.jast.java.offer.singleton.SimpleLazySingleton@2b9283d, cn.jast.java.offer.singleton.SimpleLazySingleton@72fba635]
2. 多线程工作效率不高(加锁获取实例的方法)
package cn.jast.java.offer.singleton; public class Synchronized1Singleton { private static Synchronized1Singleton instance; private Synchronized1Singleton(){ } /** * 每次获取对象时都加锁来确保创建对象 * @return */ public static synchronized Synchronized1Singleton getInstance(){ if(instance == null){ instance = new Synchronized1Singleton(); } return instance; } }
测试:
public static void testSynchronized1Singleton(){ long startTime = System.currentTimeMillis(); SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized1Singleton singleton = Synchronized1Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("执行时间:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } }
输出:
执行时间:72 ms(注:一个样例)
3. 加同步锁前后两次判断实例是否已存在
package cn.jast.java.offer.singleton; public class Synchronized2Singleton { private static Synchronized2Singleton instance; private Synchronized2Singleton(){ } public static Synchronized2Singleton getInstance(){ if(instance == null){ synchronized (Synchronized2Singleton.class){ if(instance==null){ instance = new Synchronized2Singleton(); } } } return instance; } }
4. 利用静态初始化创建实例(推荐,线程安全)
package cn.jast.java.offer.singleton; /** * 推荐 */ public class StaticInitializeSingleton { private static StaticInitializeSingleton instance ; static{ instance = new StaticInitializeSingleton(); } private StaticInitializeSingleton(){ } public static StaticInitializeSingleton getInstance(){ return instance; } }
5. 利用静态内部类实现按需创建实例(最推荐,线程安全,效率高)
package cn.jast.java.offer.singleton; /** * 推荐 */ public class StaticInnerClassSingleton { private StaticInnerClassSingleton(){ } public static StaticInnerClassSingleton getInstance(){ return Inner.instance; } private static class Inner{ private static final StaticInnerClassSingleton instance = new StaticInnerClassSingleton(); } }
完整的测试
package cn.jast.java.offer.singleton; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { public static void main(String[] args) { // testSimpleLazySingleton(); testSynchronized1Singleton(); // testSynchronized2Singleton(); // testStaticInitializeSingleton(); // testNestedClassSingleton(); } /** * 测试简单单例的线程安全 */ public static void testSimpleLazySingleton(){ SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ SimpleLazySingleton simpleLazySingleton = SimpleLazySingleton.getInstance(); singletonSet.add(simpleLazySingleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } /** * 测试线程安全的单例模式实现 */ public static void testSynchronized1Singleton(){ long startTime = System.currentTimeMillis(); Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized1Singleton singleton = Synchronized1Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("执行时间:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } /** * Synchronized2Singleton 的效率比 Synchronized1Singleton高几倍甚至几十倍以上 */ public static void testSynchronized2Singleton(){ long startTime = System.currentTimeMillis(); Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized2Singleton singleton = Synchronized2Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("执行时间:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } /** * */ public static void testStaticInitializeSingleton(){ Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized2Singleton singleton = Synchronized2Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } public static void testNestedClassSingleton(){ Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ StaticInnerClassSingleton singleton = StaticInnerClassSingleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } }
自问自答
问:单例模式获取实例的方法为什么是静态方法? 答:因为构造方法是私有的,无法通过new创建实例,那只能通过类方法获取实例。那通过反射是否可以创建实例呢?
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注创新互联行业资讯频道,感谢您对创新互联的支持。
分享文章:如何实现Singleton模式
本文网址:http://myzitong.com/article/jdegps.html