好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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多线程实战之单例模式与多线程的实例详解的详细内容...

  阅读:13次