欢迎来到代码驿站!

JAVA代码

当前位置:首页 > 软件编程 > JAVA代码

Java多线程实战之单例模式与多线程的实例详解

时间:2021-05-24 08:50:24|栏目:JAVA代码|点击:

1、立即加载/饿汉模式

// 立即加载/饿汉模式
public class MyObject {
 private static final MyObject myObject = new MyObject();
 private MyObject() {
 }
 public static MyObject getInstance() {
 return myObject;
 }
}

立即加载/饿汉模式是在类创建的同时已经创建好一个静态的对象供系统使用,不存在线程安全问题

2、延迟加载/懒汉模式

// 延迟加载/懒汉模式
public class MyObject {
 private static MyObject myObject;
 private MyObject() {
 }
 public static MyObject getInstance() {
 if (myObject == null) {
  myObject = new MyObject();
 }
 return myObject;
 }
}

延迟加载/懒汉模式是在调用方法时实例才被创建,在多线程环境下,会出现取出多个实例的情况,与单例模式的初衷是相背离的

1)、延迟加载/懒汉模式在多线程环境下创建出多个实例:

// 延迟加载/懒汉模式
public class MyObject {
 private static MyObject myObject;
 private MyObject() {
 }
 public static MyObject getInstance() {
 try {
  if (myObject == null) {
  TimeUnit.SECONDS.sleep(3);
  myObject = new MyObject();
  }
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 return myObject;
 }
}
public class MyThread extends Thread {
 @Override
 public void run() {
 System.out.println(MyObject.getInstance().hashCode());
 }
}
public class Run {
 public static void main(String[] args) {
 MyThread myThread = new MyThread();
 MyThread myThread2 = new MyThread();
 MyThread myThread3 = new MyThread();
 myThread.start();
 myThread2.start();
 myThread3.start();
 }
}

运行结果:三次打印的hashCode不完全相等

2)、通过声明synchronized关键字解决线程安全问题:

// 延迟加载/懒汉模式
public class MyObject {
 private static MyObject myObject;
 private MyObject() {
 }
 public static synchronized MyObject getInstance() {
 try {
  if (myObject == null) {
  TimeUnit.SECONDS.sleep(3);
  myObject = new MyObject();
  }
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 return myObject;
 }
}

使用synchronized关键字,这种方法的运行效率很低,是同步运行的,下一个线程想要取得对象,则必须等上一个线程释放锁之后,才可以继续执行

3)、使用同步代码块解决线程安全问题:

// 延迟加载/懒汉模式
public class MyObject {
 private static MyObject myObject;
 private MyObject() {
 }
 public static MyObject getInstance() {
 try {
  // 相当于public static synchronized MyObject getInstance()
  synchronized (MyObject.class) {
  if (myObject == null) {
   TimeUnit.SECONDS.sleep(3);
   myObject = new MyObject();
  }
  }
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 return myObject;
 }
}

加入同步代码块,这种方法的运行效率也是非常低,和synchronized同步方法一样是同步运行的

4)、针对某些重要的代码进行单独的同步

// 延迟加载/懒汉模式
public class MyObject {
 private static MyObject myObject;
 private MyObject() {
 }
 public static MyObject getInstance() {
 try {
  if (myObject == null) {
  TimeUnit.SECONDS.sleep(3);
  synchronized (MyObject.class) {
   myObject = new MyObject();
  }
  }
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 return myObject;
 }
}

此方法只对实例化对象的关键代码进行同步,从语句的结构上来讲,运行的效率的确得到了提升。但如果是多线程的情况下还是无法解决得到同一个实例对象的结果

5)、使用DCL双检查锁机制

// 延迟加载/懒汉模式
public class MyObject {
 private volatile static MyObject myObject;
 private MyObject() {
 }
 public static MyObject getInstance() {
 try {
  if (myObject == null) {
  TimeUnit.SECONDS.sleep(3);
  synchronized (MyObject.class) {
   if (myObject == null) {
   myObject = new MyObject();
   }
  }
  }
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 return myObject;
 }
}

使用DCL双检查锁机制,既保证了不需要同步代码的异步执行性,又保证了单例的效果

3、使用静态内部类实现单例模式

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

4、使用静态代码块实现单例模式

public class MyObject {
 private static MyObject instance = null;
 private MyObject() {
 }
 static {
 instance = new MyObject();
 }
 public static MyObject getInstance() {
 return instance;
 }
}

5、使用enum枚举实现单例模式

public class MyObject {
 public enum MyEnumSingleton {
 objectFactory;
 private MyObject myObject;
 private MyEnumSingleton() {
  myObject = new MyObject();
 }
 public MyObject getInstance() {
  return myObject;
 }
 }
 public static MyObject getInstance() {
 return MyEnumSingleton.objectFactory.getInstance();
 }
}

枚举enum和静态代码块的特性相似,在使用枚举类时,构造方法会被自动调用,使用这个特性实现单例设计模式

总结

上一篇:Java排序算法之SleepSort排序示例

栏    目:JAVA代码

下一篇:win10系统64位jdk1.8的下载与安装教程图解

本文标题:Java多线程实战之单例模式与多线程的实例详解

本文地址:http://www.codeinn.net/misctech/127884.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有