Java安全的发布对象

安全发布对象

  • 在静态初始化函数中初始化一个对象引用
  • 将对象的引用保存到volatile类型域或者AtomicReference对象中
  • 将对象的引用保存到某个正确构造对象的final类型域中
  • 将对象的引用保存到一个由锁保护的域中

Spring 框架中,Spring管理的类都是单例模式。如何保证一个实例只被初始化一次,且线程安全?通过不同单例的写法,具体描述安全发布对象的四种方法:

在静态初始化函数中初始化一个对象的引用(不推荐)

  1. package com.rumenz.task.single;
  2. //线程安全
  3. //饿汉模式
  4. //静态代码块初始化
  5. public class SingletonExample {
  6. private SingletonExample(){
  7. //初始化操作
  8. }
  9. private static SingletonExample singletonExample=null;
  10. static {
  11. singletonExample=new SingletonExample();
  12. }
  13. public static SingletonExample getInstance(){
  14. return singletonExample;
  15. }
  16. }
  17. //或者
  18. package com.rumenz.task.single;
  19. //线程安全
  20. //饿汉模式
  21. //静态代码块初始化
  22. public class SingletonExample {
  23. private SingletonExample(){
  24. //初始化操作
  25. }
  26. private static SingletonExample singletonExample=new SingletonExample();
  27. public static SingletonExample getInstance(){
  28. return singletonExample;
  29. }
  30. }

缺点:用不用都会初始化对象,如果初始化工作较多,加载速度会变慢,影响系统性能。

将对象的引用保存到volatile类型或AtomicReference对象中(推荐)

  1. package com.rumenz.task.single;
  2. //线程安全
  3. //懒汉模式
  4. public class SingletonExample1 {
  5. private SingletonExample1() {
  6. //初始化操作
  7. }
  8. // 1、memory = allocate() 分配对象的内存空间
  9. // 2、ctorInstance() 初始化对象
  10. // 3、instance = memory 设置instance指向刚分配的内存
  11. // 单例对象 volatile + 双重检测机制 -> 禁止指令重排
  12. private volatile static SingletonExample1 singletonExample1=null;
  13. //静态工厂方法
  14. public static SingletonExample1 getInstance(){
  15. if(singletonExample1==null){ //双重检测
  16. synchronized(SingletonExample1.class){ //同步锁
  17. if(singletonExample1==null){
  18. singletonExample1=new SingletonExample1();
  19. }
  20. }
  21. }
  22. return singletonExample1;
  23. }
  24. }
  25. //或者
  26. package com.rumenz.task.single;
  27. import java.util.concurrent.atomic.AtomicReference;
  28. class SingletonAtomicReference<T> {
  29. /**
  30. * Implement the singleton using an AtomicReference.
  31. */
  32. public static AtomicReference<SingletonAtomicReference> sSingletonAR =
  33. new AtomicReference<>(null);
  34. /**
  35. * Define a non-static field.
  36. */
  37. private T mField;
  38. /**
  39. * * @return The value of the field.
  40. */
  41. public T getField() {
  42. return mField;
  43. }
  44. /**
  45. * Set and return the value of the field.
  46. */
  47. public T setField (T f) { return mField = f; }
  48. /**
  49. * The static instance() method from the Singleton pattern.
  50. */
  51. public static <T> SingletonAtomicReference instance() {
  52. // Get the current value of the singleton.
  53. SingletonAtomicReference<T> singleton = sSingletonAR.get();
  54. // Run this code if the singleton is not yet initialized.
  55. if (singleton == null) {
  56. singleton = new SingletonAtomicReference<>();
  57. //CAS
  58. if (!sSingletonAR.compareAndSet(null, singleton))
  59. singleton = sSingletonAR.get();
  60. }
  61. // Return the singleton's current value.
  62. return singleton;
  63. }
  64. }
  65. class R{
  66. private Integer age;
  67. public Integer getAge() {
  68. return age;
  69. }
  70. public void setAge(Integer age) {
  71. this.age = age;
  72. }
  73. public R(Integer age) {
  74. this.age = age;
  75. }
  76. public static void main(String[] args) {
  77. R o = (R)SingletonAtomicReference.instance().setField(new R(300));
  78. System.out.println(o.getAge());
  79. }
  80. }

优点:按需加载
缺点:第一次初始化的时候可能会比较慢

通过synchronized(不推荐)

  1. package com.rumenz.task.single;
  2. public class SingletonExample3 {
  3. //私有构造函数
  4. private SingletonExample3(){
  5. //初始化操作
  6. }
  7. private static SingletonExample3 singletonExample3=null;
  8. //静态的工厂方法
  9. public static synchronized SingletonExample3 getSingletonExample3(){
  10. if(singletonExample3==null){
  11. singletonExample3=new SingletonExample3();
  12. }
  13. return singletonExample3;
  14. }
  15. }

缺点:每次进入getSingletonExample3都会加锁,耗费资源,故不推荐使用。

枚举(推荐)

  1. package com.rumenz.task.single;
  2. public class SingletonExample4 {
  3. //私有构造函数
  4. private SingletonExample4(){
  5. //初始化
  6. }
  7. public static SingletonExample4 getSingletonExample4(){
  8. return Singleton.INSTANCE.getSingleton();
  9. }
  10. private enum Singleton{
  11. INSTANCE;
  12. private SingletonExample4 singleton;
  13. Singleton(){
  14. singleton=new SingletonExample4();
  15. }
  16. public SingletonExample4 getSingleton(){
  17. return singleton;
  18. }
  19. }
  20. }

优点:天然线程安全,可防止反射生成实例,推荐使用

返回笔记列表
入门小站