这里我们介绍一下在多线程中如何安全正确的编写单例模式的代码。不知为何,恰如其分的话总是姗姗来迟,错过最恰当的时机。

多线程中的单例模式

  这里面通过代码来体会一下在多线程中如何正确的编写单例模式的代码。相同的代码如下,不同的是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;
}
}

安全:一次的打印结果如下


二、延迟加载方式(懒汉模式)

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;
}
}

不正确:一次的打印结果


三、延迟加载解决方案之声明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;
}
}

安全:一次的打印结果


效率比较低下:同步运行,下一个线程想要取得对象,则必须等待上一个线程释放锁之后,才可以继续执行。

四、延迟加载解决方案之同步代码块

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;
}
}

安全:一次的打印结果如下


效率比较低下:和上述的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;
}
}

不安全:一次的打印结果如下


六、延迟加载解决方案之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;
}
}

安全:一次的打印结果如下


使用双重检查锁功能,成功地解决了“懒汉模式”遇到多线程的问题。DCL也是大多数多线程结合单例模式使用的解决方案。

七、使用静态内置类实现单例模式

public class MyObject7 {
private static class MyObjectHandler {
private static MyObject7 myObject = new MyObject7();
} private MyObject7() {} public static MyObject7 getInstance() {
return MyObjectHandler.myObject;
}
}

安全:一次的打印结果如下


八、使用static代码块实现单例模式

public class MyObject8 {
private static MyObject8 myObject = null; static {
myObject = new MyObject8();
} private MyObject8() {} public static MyObject8 getInstance() {
return myObject;
}
}

安全:一次的打印结果如下


友情链接

java高级---->Thread之单例模式的使用的更多相关文章

  1. java高级---->Thread之ScheduledExecutorService的使用

    ScheduledExecutorService的主要作用就是可以将定时任务与线程池功能结合使用.今天我们来学习一下ScheduledExecutorService的用法.我们都太渺小了,那么容易便湮 ...

  2. java高级---->Thread之ExecutorService的使用

    今天我们通过实例来学习一下ExecutorService的用法.我徒然学会了抗拒热闹,却还来不及透悟真正的冷清. ExecutorService的简单实例 一.ExecutorService的简单使用 ...

  3. java高级---->Thread之Phaser的使用

    Phaser提供了动态增parties计数,这点比CyclicBarrier类操作parties更加方便.它是jdk1.7新增的类,今天我们就来学习一下它的用法.尘埃落定之后,回忆别来挑拨. Phas ...

  4. java高级---->Thread之CompletionService的使用

    CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样可以将执行任务与处理任务分离开来进行处理.今天我们通过实例来学习一下CompletionServi ...

  5. java高级---->Thread之CyclicBarrier的使用

    CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).今天我们就学习一下CyclicBarrier的用法. Cycl ...

  6. java高级---->Thread之BlockingQueue的使用

    今天我们通过实例来学习一下BlockingQueue的用法.梦想,可以天花乱坠,理想,是我们一步一个脚印踩出来的坎坷道路. BlockingQueue的实例 官方文档上的对于BlockingQueue ...

  7. java高级---->Thread之Exchanger的使用

    Exchanger可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据.今天我们就通过实例来学习一下Exchanger的用法. Exchanger的简单实例 Exchanger是 ...

  8. java高级---->Thread之FutureTask的使用

    FutureTask类是Future 的一个实现,并实现了Runnable,所以可通过Excutor(线程池) 来执行,也可传递给Thread对象执行.今天我们通过实例来学习一下FutureTask的 ...

  9. java高级---->Thread之Condition的使用

    Condition 将 Object 监视器方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set ...

随机推荐

  1. (转)simple-framework(MaliSDK框架分析)

     出自:http://blog.csdn.net/u013467442/article/details/46940501 simple-framework(Mali SDK框架分析) 1.所有的定义及 ...

  2. 【Hibernate步步为营】--最后的集合映射

    上篇文章具体讨论了组合对象映射的原理.它事实上指的是怎样将对象模型中的组合关系映射到关系模型中,它是通过使用Hibernate提供的<component>标签来实现的,并须要在该标签中加入 ...

  3. win10 UWP Markdown 含源码

    Windows下没有比較好的Markdown编辑器 我就自己写一个 csdn的Markdown非常好,就是我须要截图保存有麻烦 须要把我的截图保存在本地,然后上传 这个过程比較麻烦 csdn的图没法外 ...

  4. EF5+MVC4系列(9) Razor视图引擎的核心原理;@符号的使用;输出html的转义

    一:Razor视图引擎的核心原理 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项 ,他是一个视图引擎 他的核心原理,就是当读取到 @符号的时候,就认为这是开始 ...

  5. 说说PHP中foreach引用的一个坑

    From: http://blog.csdn.net/yipiankongbai/article/details/45307767 先来看看下面这段代码: <?php $arr = array( ...

  6. json过滤某些属性 之@jsonignore

    Jackson相关: 使用Jackson相关的注解时一定要注意自己定义的属性命名是否规范. 命名不规范时会失去效果.(例如Ename ,Eage 为不规范命名.“nameE”,“ageE”为规范命名) ...

  7. phd文献阅读日志-博一下学期

    博一下学期: 1.week1,2018.2.26 2006-Extreme learning machine: theory and applications 期刊来源:Huang G B, Zhu ...

  8. mysql中explain

    1.select_type: /* select_type 使用 SIMPLE */explain select * from tb_shop_order where id='201603292570 ...

  9. 用Lua实现string的trim()方法

    function trim1(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end -- from PiL2 20.4 fu ...

  10. bat 变量作用域

    set answer=one if true equ true ( set answer=two echo %answer% ) echo Argument is %answer% pause