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