多线程下的单例模式
来源:互联网 发布:死寂木偶比利淘宝 编辑:程序博客网 时间:2024/06/18 12:11
设计模式之(单例模式)
java的单例模式是一种常见的设计模式,单例模式的写法有好几种,主要分为懒汉式单例,饿汉式单例还有登记式单例
下面我们要介绍的就是多线程下的单例模式,多线程,我们以继承Thread和实现Runnable接口为主
首先我们以饿汉模式为例
package lock;public class EhanSingleton { /*饿汉加载模式/立即加载模式*/ //初始化构造函数 private EhanSingleton(){ } private static EhanSingleton ehan = new EhanSingleton(); public static EhanSingleton getInstance(){ try { Thread.sleep(3000); //方便多线程测试 } catch (InterruptedException e) { e.printStackTrace(); } return ehan ; }}
然后我们创建多个线程来测试一下
package lock;public class MyThread extends Thread{ @Override public void run() { System.out.println(EhanSingleton.getInstance()); } public static void main(String[] args) { MyThread m1 = new MyThread(); MyThread m12 = new MyThread(); MyThread m13 = new MyThread(); m1.start(); m12.start(); m13.start(); }}测试结果为:
cn.spring.dxcDanli.Singleton@132965a8
cn.spring.dxcDanli.Singleton@132965a8
cn.spring.dxcDanli.Singleton@132965a8
显示为三个相同的内存地址,说明这个模式符合单例
第二种模式为懒汉模式
package lock;public class LanHanSingleton { /*懒汉模式/延迟加载*/ //私有化构造函数 private LanHanSingleton(){ } private static LanHanSingleton lanHanSingleton ; public static LanHanSingleton getInstance() { if(lanHanSingleton == null){ try { Thread.sleep(3000); lanHanSingleton = new LanHanSingleton() ; } catch (InterruptedException e) { e.printStackTrace(); } } return lanHanSingleton ; }}我在用多线程去测试一下是否每个对象的HashCode的值是保持一致的
package lock;public class MyThread extends Thread{ @Override public void run() { System.out.println(LanHanSingleton.getInstance().hashCode()); } public static void main(String[] args) { MyThread m1 = new MyThread(); MyThread m12 = new MyThread(); MyThread m13 = new MyThread(); m1.start(); m12.start(); m13.start(); }}
测试结果如下:
126720696
137014984
1638443495
测试的结果发现 这个已经不符合单例模式,他们并不是同一个对象了,而是几个不同的对象,所以这种懒汉模式在单线程中是符合单例模式的,不过在多线程环境中是不符合单例模式
想到这里,大家肯定会想到了synchrinized关键字,我们在来看看效果
package lock;public class LanHanSingleton { /*懒汉模式/延迟加载*/ //私有化构造函数 private LanHanSingleton(){ } private static LanHanSingleton lanHanSingleton ; public synchronized static LanHanSingleton getInstance() { if(lanHanSingleton == null){ try { Thread.sleep(3000); lanHanSingleton = new LanHanSingleton() ; } catch (InterruptedException e) { e.printStackTrace(); } } return lanHanSingleton ; }}测试结果如下
1638443495
1638443495
1638443495
大家发现这样的确可以解决多线程带来的不同对象所导致的问题,但是这个方法并不好,这种方法效率非常低下,一定要等到上一个线程释放锁以后才能获取对象
同步方法是对整个方法持有锁,这个对于效率来说实在太慢,大家还会想到用同步块,那么我们在试一试
package lock;public class LanHanSingleton { /*懒汉模式/延迟加载*/ //私有化构造函数 private LanHanSingleton(){ } private static LanHanSingleton lanHanSingleton ; public static LanHanSingleton getInstance() { try { synchronized (LanHanSingleton.class) { if(lanHanSingleton == null){ Thread.sleep(3000); lanHanSingleton = new LanHanSingleton() ; } } } catch (InterruptedException e) { e.printStackTrace(); } return lanHanSingleton ; }}
其实这个效果和上个效果差不多,效率都是比较慢的,和同步方法synchronized一样是同步运行的
这里最好的方式就是DCL双检查锁机制,也就是同步代码块
package lock;public class LanHanSingleton { /*懒汉模式/延迟加载*/ //私有化构造函数 private LanHanSingleton(){ } private static LanHanSingleton lanHanSingleton ; public static LanHanSingleton getInstance() { try { if(lanHanSingleton == null){ synchronized (LanHanSingleton.class) { if(lanHanSingleton == null){ lanHanSingleton = new LanHanSingleton() ; } } } } catch (InterruptedException e) { e.printStackTrace(); } return lanHanSingleton ; }}
阅读全文
1 0
- Java 多线程下的单例模式
- Java 多线程下的单例模式
- Java 多线程下的单例模式
- 多线程下的C++ 单例模式
- 多线程下的单例模式
- 多线程下的单例模式
- Java 多线程下的单例模式
- 多线程下的单例设计模式
- Java 多线程下的单例模式
- Java 多线程下的单例模式
- Java 多线程下的单例模式
- Java 多线程下的单例模式
- 多线程下的单例模式
- 多线程下的单例模式
- 多线程下的单例模式
- Java 多线程下的单例模式
- 多线程并发下的单例模式
- 多线程下的单例模式
- android中播放视频
- Spring的ApplicationContext的生命周期
- Liunx上安装及使用Nginx
- 9.线程
- servlet jsp一套完整的增删查改思路
- 多线程下的单例模式
- java 观察者模式 简明版
- Caffe中学习率策略应如何选择
- java js 文件图片通过FTP进行上传和同步
- Android实现https单双向认证及自签名证书生成方法
- 笨方法学Python 习题 4: 变量(variable)和命名
- springmvc文件下载
- Python的if判断以及for循环、range()函数
- 将excel导入mysql(使用navicat)