java高级---->Thread之单例模式的使用
这里我们介绍一下在多线程中如何安全正确的编写单例模式的代码。不知为何,恰如其分的话总是姗姗来迟,错过最恰当的时机。
多线程中的单例模式
这里面通过代码来体会一下在多线程中如何正确的编写单例模式的代码。相同的代码如下,不同的是Object这个类。
package com.linux.huhx.thread3.singleDesign_1;
/**
* @Author: huhx
* @Date: 2017-10-31 下午 4:28
*/
public class SingleDesignTest1 {
public static void main(String[] args) {
MyThread[] threads = new MyThread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new MyThread();
}
for (int i = 0; i < 10; i++) {
threads[i].start();
}
}
static class MyThread extends Thread {
@Override
public void run() {
System.out.println(MyObject*.getInstance().hashCode());
}
}
}
以下的不同测试类的结果,都是基于修改MyThread里面run方法的MyObject*的值。
一、立即加载方式(饿汉模式)
public class MyObject1 {
private static MyObject1 myObject = new MyObject1();
private MyObject1() {}
public static MyObject1 getInstance() {
return myObject;
}
}
安全:一次的打印结果如下
1508118770
1508118770
1508118770
1508118770
1508118770
1508118770
1508118770
1508118770
1508118770
1508118770
二、延迟加载方式(懒汉模式)
public class MyObject2 {
private static MyObject2 myObject;
private MyObject2() {}
public static MyObject2 getInstance() {
try {
if (myObject == null) {
// 模拟一些准备的耗时操作
TimeUnit.SECONDS.sleep(2);
myObject = new MyObject2();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
不正确:一次的打印结果
401241377
355159803
1875573029
797782832
1696014491
1060834655
961745937
1060834655
1312341120
985396398
三、延迟加载解决方案之声明synchronized
public class MyObject3 {
private static MyObject3 myObject;
private MyObject3() {}
public synchronized static MyObject3 getInstance() {
try {
if (myObject == null) {
// 模拟一些准备的耗时操作
TimeUnit.SECONDS.sleep(2);
myObject = new MyObject3();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
安全:一次的打印结果
774263507
774263507
774263507
774263507
774263507
774263507
774263507
774263507
774263507
774263507
效率比较低下:同步运行,下一个线程想要取得对象,则必须等待上一个线程释放锁之后,才可以继续执行。
四、延迟加载解决方案之同步代码块
public class MyObject4 {
private static MyObject4 myObject;
private MyObject4() {}
public static MyObject4 getInstance() {
try {
synchronized (MyObject4.class) {
if (myObject == null) {
// 模拟一些准备的耗时操作
TimeUnit.SECONDS.sleep(2);
myObject = new MyObject4();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
安全:一次的打印结果如下
1373650392
1373650392
1373650392
1373650392
1373650392
1373650392
1373650392
1373650392
1373650392
1373650392
效率比较低下:和上述的synchronized同步方法一样都是同步运行的。
五、延迟加载解决方案之同步部分代码块
public class MyObject5 {
private static MyObject5 myObject;
private MyObject5() {}
public static MyObject5 getInstance() {
try {
if (myObject == null) {
// 模拟一些准备的耗时操作
TimeUnit.SECONDS.sleep(2);
synchronized (MyObject5.class) {
myObject = new MyObject5();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
不安全:一次的打印结果如下
401241377
1696014491
797782832
1875573029
1060834655
43626537
1971360294
1312341120
961745937
860826410
六、延迟加载解决方案之DCL双检查锁机制
public class MyObject6 {
private volatile static MyObject6 myObject;
private MyObject6() {}
public static MyObject6 getInstance() {
try {
if (myObject == null) {
// 模拟一些准备的耗时操作
TimeUnit.SECONDS.sleep(2);
synchronized (MyObject6.class) {
if (myObject == null) {
myObject = new MyObject6();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
安全:一次的打印结果如下
1312341120
1312341120
1312341120
1312341120
1312341120
1312341120
1312341120
1312341120
1312341120
1312341120
使用双重检查锁功能,成功地解决了“懒汉模式”遇到多线程的问题。DCL也是大多数多线程结合单例模式使用的解决方案。
七、使用静态内置类实现单例模式
public class MyObject7 {
private static class MyObjectHandler {
private static MyObject7 myObject = new MyObject7();
}
private MyObject7() {}
public static MyObject7 getInstance() {
return MyObjectHandler.myObject;
}
}
安全:一次的打印结果如下
1240673261
1240673261
1240673261
1240673261
1240673261
1240673261
1240673261
1240673261
1240673261
1240673261
八、使用static代码块实现单例模式
public class MyObject8 {
private static MyObject8 myObject = null;
static {
myObject = new MyObject8();
}
private MyObject8() {}
public static MyObject8 getInstance() {
return myObject;
}
}
安全:一次的打印结果如下
1875573029
1875573029
1875573029
1875573029
1875573029
1875573029
1875573029
1875573029
1875573029
1875573029
作者:
huhx
出处: www.cnblogs.com/huhx
格言:你尽力了,才有资格说自己的运气不好。
版权:本文版权归作者huhx和博客园共有,欢迎转载。未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
出处: www.cnblogs.com/huhx
格言:你尽力了,才有资格说自己的运气不好。
版权:本文版权归作者huhx和博客园共有,欢迎转载。未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!