gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Java多线程实战之单例模式与多线程的实例详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

1、立即加载/饿汉模式 。

?
1
2
3
4
5
6
7
8
9
// 立即加载/饿汉模式
public class myobject {
  private static final myobject myobject = new myobject();
  private myobject() {
  }
  public static myobject getinstance() {
  return myobject;
  }
}

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

2、延迟加载/懒汉模式 。

?
1
2
3
4
5
6
7
8
9
10
11
12
// 延迟加载/懒汉模式
public class myobject {
  private static myobject myobject;
  private myobject() {
  }
  public static myobject getinstance() {
  if (myobject == null ) {
   myobject = new myobject();
  }
  return myobject;
  }
}

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 延迟加载/懒汉模式
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;
  }
}
?
1
2
3
4
5
6
public class mythread extends thread {
  @override
  public void run() {
  system.out.println(myobject.getinstance().hashcode());
  }
}
?
1
2
3
4
5
6
7
8
9
10
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关键字解决线程安全问题:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 延迟加载/懒汉模式
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)、使用同步代码块解决线程安全问题:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 延迟加载/懒汉模式
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)、针对某些重要的代码进行单独的同步 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 延迟加载/懒汉模式
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双检查锁机制 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 延迟加载/懒汉模式
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、使用静态内部类实现单例模式 。

?
1
2
3
4
5
6
7
8
9
10
public class myobject {
  private static class myobjecthandler {
  private static myobject myobject = new myobject();
  }
  private myobject() {
  }
  public static myobject getinstance() {
  return myobjecthandler.myobject;
  }
}

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

?
1
2
3
4
5
6
7
8
9
10
11
public class myobject {
  private static myobject instance = null ;
  private myobject() {
  }
  static {
  instance = new myobject();
  }
  public static myobject getinstance() {
  return instance;
  }
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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和静态代码块的特性相似,在使用枚举类时,构造方法会被自动调用,使用这个特性实现单例设计模式 。

总结 。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我的支持。如果你想了解更多相关内容请查看下面相关链接 。

原文链接:https://blog.csdn.net/qq_40378034/article/details/86765986 。

最后此篇关于Java多线程实战之单例模式与多线程的实例详解的文章就讲到这里了,如果你想了解更多关于Java多线程实战之单例模式与多线程的实例详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com