Java 单例模式
2016-07-27 00:00
357 查看
#单例模式
##一.代码实现
###1.饿汉式
声明为静态类变量,在类加载时初始化,因此不会有线程安全问题,若未被调用则会造成资源浪费。
使用静态代码块,在类加载时初始化,因此不会有线程安全问题,若未被调用则会造成资源浪费。
###2.懒汉式
延迟加载,但多线程情况下会产生线程安全问题
延迟加载,多线程情况下不会产生线程安全问题,但效率不高
双检索机制,延迟加载,多线程情况下不会产生线程安全问题,只在第一次创建时进行同步。但由于JVM底层内部模型原因,偶尔会出现问题。
将instance声明为volatile即可排除问题,试用与JDK1.5以后
###3.静态内部类
在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。且类的静态属性只在第一次类加载时初始化,所以是线程安全的。
枚举的方式
###4.用ThreadLocal实现
每个线程借助于ThreadLocal,用来标示每个线程是否已访问过,如果访问过,则不再需要走同步块,提高了一定的效率。
##一.代码实现
###1.饿汉式
public class Singleton1 { private static final Singleton1 INSTANCE = new Singleton1(); private Singleton1(){} public static Singleton1 getInstance(){ return INSTANCE; } }
声明为静态类变量,在类加载时初始化,因此不会有线程安全问题,若未被调用则会造成资源浪费。
public class Singleton3 { private static Singleton3 SINGLETON=null; private Singleton3() {} static{ SINGLETON=new Singleton3(); } public Singleton3 getInstance(){ return SINGLETON; } }
使用静态代码块,在类加载时初始化,因此不会有线程安全问题,若未被调用则会造成资源浪费。
###2.懒汉式
public class Singleton2 { private static Singleton2 instance = null; private Singleton2() { } public static Singleton2 getInstance() { if (instance == null) { instance = new Singleton2(); } return instance; } }
延迟加载,但多线程情况下会产生线程安全问题
public class Singleton4 { private static Singleton4 instance = null; private Singleton4() { } public static synchronized Singleton4 getInstance() { if (instance == null) { instance = new Singleton4(); } return instance; } }
延迟加载,多线程情况下不会产生线程安全问题,但效率不高
public class Singleton5 { private static Singleton5 instance = null; private Singleton5() { } public static Singleton5 getInstance() { if (instance == null) { synchronized (Singleton5.class) { if (instance == null) { instance = new Singleton5(); } } } return instance; } }
双检索机制,延迟加载,多线程情况下不会产生线程安全问题,只在第一次创建时进行同步。但由于JVM底层内部模型原因,偶尔会出现问题。
public class Singleton5 { private static volatile Singleton5 instance = null; private Singleton5() { } public static Singleton5 getInstance() { if (instance == null) { synchronized (Singleton5.class) { if (instance == null) { instance = new Singleton5(); } } } return instance; }
将instance声明为volatile即可排除问题,试用与JDK1.5以后
###3.静态内部类
public class Singleton6 { private Singleton6() { } private static class SingletonInstance { private static final Singleton6 INSTANCE = new Singleton6(); } public static Singleton6 getInstance() { return SingletonInstance.INSTANCE; } }
在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。且类的静态属性只在第一次类加载时初始化,所以是线程安全的。
public enum Singleton7 { INSTANCE; }
枚举的方式
###4.用ThreadLocal实现
public class Singleton8 { private static final ThreadLocal threadLocal = new ThreadLocal(); private static Singleton8 singleton8; private Singleton8() { } public static Singleton8 getInstance() { if (threadLocal.get() == null) { // 每个线程第一次都会调用 createInstance(); } return singleton8; } private static final void createInstance() { synchronized (Singleton8.class) { if (singleton8 == null) { singleton8 = new Singleton8(); } } threadLocal.set(threadLocal); } }
每个线程借助于ThreadLocal,用来标示每个线程是否已访问过,如果访问过,则不再需要走同步块,提高了一定的效率。
相关文章推荐
- Spring定时任务的几种实现
- Java参数参考
- java线程同步(一)
- Java线程同步(二)
- MyEclipse快捷键设置
- 多线程(7)-java多线程之Lock物语
- 详解spring 每个jar的作用
- Java常见的几种内存溢出及解决方法
- java可变参数
- java异常
- Idea 第一次亲密接触
- eclipse maven配置注意
- eclipse 启动失败
- Marklogic学习 由浅入深(10)—— 用Eclipse写Marklogic程序
- Java值得注意的知识点
- 一个经典例子让你彻彻底底理解java回调机制
- Java编程---4、用递归的方法查询出某一文件夹下所有文件夹和文件的名称
- 深入JVM 第一章 之2
- java编程---3.2 (关于String的练习题) 统计字符串中每个字符的个数,例如:把aaaabbaaccbb变成a6b4c2
- Java线程优先级