Java设计模式-单例模式及线程安全问题
来源:互联网 发布:淘宝装修消除模块间距 编辑:程序博客网 时间:2024/05/22 03:30
单例模式是非常常用的设计模式,他确保了一个类只有一个对象,并且这个对象是自己创建的,外界可以获取使用到这个对象。
单例模式一般有两种:懒汉式,饿汉式(其实还有一种登记式,把创建的对象放在map集合中,有就直接用,没有就创建)
单例模式通过构造方法私有化,外界无法创建对象,下面是两种单例的实现
饿汉式:
package demo_singleton;public class SingletonHungry { private static SingletonHungry singletonhunary = new SingletonHungry(); public static SingletonHungry getinstance() { return singletonhunary; } private SingletonHungry() { }}
懒汉式:
package demo_singleton;/*懒汉式的单例模式,有线程安全问题,当多线程访问的时候,会出现多个实例*/public class SingletonLazy { private static SingletonLazy instance = null; public static SingletonLazy getInstance() { if (instance == null) { instance = new SingletonLazy(); } return instance; } private SingletonLazy() { }}
多线程环境下的测试:
懒汉式测试:
package demo_singleton;public class TestLary extends Thread{ public static void main(String[] args) { TestLary t1 = new TestLary(); TestLary t2 = new TestLary(); TestLary t3 = new TestLary(); t1.start(); t2.start(); t3.start(); } public void run() { System.out.println(SingletonLazy.getInstance()); }}
输出结果:
demo_singleton.SingletonLazy@529e3fc2demo_singleton.SingletonLazy@529e3fc2demo_singleton.SingletonLazy@136c03ee
通过输出结果可以看到,其实创建了两个对象
饿汉式测试:
package demo_singleton;public class TestHungry extends Thread { public static void main(String[] args) { TestHungry t1 = new TestHungry(); TestHungry t2 = new TestHungry(); TestHungry t3 = new TestHungry(); t1.start(); t2.start(); t3.start(); } @Override public void run() { System.out.println(SingletonHungry.getinstance()); }}
输出结果:
demo_singleton.SingletonHungry@6d15a113demo_singleton.SingletonHungry@6d15a113demo_singleton.SingletonHungry@6d15a113在多线程下饿汉式没有出现问题
在单线程的环境下,单例可以实现,当在多线程的条件下,懒汉式的单例就会出现线程安全问题,而饿汉式不会出现。饿汉式代码简单所以线程安全,在类加载的时候创建对象,懒汉式不会再在载的时候创建对象,效率高。代码中有判断对象是否存在的代码,所以线程不安全饿汉式不需要关注多线程问题,写法简单,但是有个缺点,就是不管你用或者不用,在类加载的时候他都会创建对象,而懒汉式的特点是延时加载,但是又带来了线程问题。既然这样我们就要解决它
开始解决懒汉式的问题,最开始想到的是同步,加上synchronized关键字:
优化一:
package demo_singleton;public class SingletonLazy1 { private static SingletonLazy1 instance1 = null; public static synchronized SingletonLazy1 getInstance() { if (instance1 == null) { instance1 = new SingletonLazy1(); } return instance1; } private SingletonLazy1() { }}
优化二:
加入同步块,对代码进行操作
package demo_singleton;/*加同步块的单例,效率有问题*/public class SingletonLazy2 { private static SingletonLazy2 instance2 = null; public static SingletonLazy2 getInstance() { synchronized (SingletonLazy2.class) { if (instance2 == null) { instance2 = new SingletonLazy2(); } } return instance2; } private SingletonLazy2() { }}
优化三:
package demo_singleton;public class SingletonLazy3 { private static SingletonLazy3 instace3 = null; public static SingletonLazy3 getInstance() { if (instace3 == null) { synchronized (SingletonLazy3.class) { if (instace3 == null) { instace3 = new SingletonLazy3(); } } } return instace3; } private SingletonLazy3() { }}
相对于前两个优化,利用同步解决线程问题,第三个利用两个判断,当程序判断对象没有创建的时候进入执行同步代码块,创建对象。在下次判断对象存在的时候,不会再执行同步代码块中的代码,相对于前两个效率会搞一些
优化四:
package demo_singleton;public class SingletonLazy4 { private static SingletonLazy4 instance4 = null; static{ instance4 = new SingletonLazy4(); } public static SingletonLazy4 getInstance() { return instance4; } private SingletonLazy4() { }}
利用static静态代码块的特点,创建对象,static代码块在类加载的时候最开始执行并且只会执行一次
优化五:
package demo_singleton;public class SingletonLazy5 { private static class Sing { private static SingletonLazy5 instance = new SingletonLazy5(); } public static SingletonLazy5 getInstance() { return Sing.instance; } private SingletonLazy5() { }}
利用静态内部类,内部类在编译的时候也是一个单独的class文件,在调用的时候会执行,不调用的时候不会执行
注意:利用Java的反射机制也是可以破坏单例的
参考:http://blog.csdn.net/cselmu9/article/details/51366946
阅读全文
0 0
- Java设计模式-单例模式及线程安全问题
- 单例模式及线程安全问题
- java单例模式的线程安全问题
- Java单例模式中的线程安全问题
- 解决单例设计模式中懒汉式线程安全问题
- 解决单例设计模式中懒汉式线程安全问题
- 单例模式的实现,及线程安全问题
- Java 单例模式 安全问题
- 对于java单例模式线程安全问题的思考
- 设计模式——单例模式(Java)——考虑多线程环境下的线程安全问题
- Java 多线程学习笔记(十一) 单例设计模式(延迟加载/懒汉模式)DCL解决线程安全问题
- 单例模式的线程安全问题
- 关于单例模式线程安全问题
- 单例模式的线程安全问题
- 单例模式与线程安全问题浅析
- 单例模式中的线程安全问题
- 单例模式的线程安全问题
- 单例模式的线程安全问题
- [iOS]系统TabBar简单使用
- c拾遗
- 震网三代在metasploit-framework上的复现与利用
- 浅谈机器学习用来做什么,它是如果工作的
- iOS之《Effective Objective-C 2.0》读书笔记(17)
- Java设计模式-单例模式及线程安全问题
- js验证带小数点的数字
- 百万级开源MQTT消息服务器 搭建
- Netty4.0学习笔记系列之五:自定义通讯协议
- linux 下 进程与线程
- html3D网页实例
- (转)什么是Floyd算法:从i号顶点到j号顶点只经过 前 k号点的最短路程
- 左偏树
- 在eclipse中利用条件断点打印log