浅谈单例模式的实现方式2 n& n0 o& u. T
单例模式(来自菜鸟教程)/ d( G1 Y% Y$ z( Y
8 @$ ^0 W+ h1 X/ z( ^" ?单例模式(Singleton Pattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。0 H+ s% O0 h5 \+ A8 m) G
单例模式的要求+ i3 C$ f$ P& ?, H- }
3 ^* Z. ^" Y+ _" ?0 O- G# `构造方法必须私有化(确保只有自己能创建)% z. @0 M+ A- h7 c4 F# A
以静态方法返回实例(外界不能通过new来获取到对象)+ I* J* W! j" k! Z
确保对象实例只有一个(只对类进行一次实例化,以后都直接获取第一次实例化的对象)
0 s4 @* n( z* Q& k9 a/ s8 ~单例模式的实现+ ]( \7 h5 J1 X7 B: s$ n
" ?4 Y: R/ _5 a: r& K, ?6 W1、懒汉式(线程不安全)# Q) x1 z. l( b/ r) O, ?
6 W$ ^& k" L4 d. ?9 A1 T6 E. P
描述:这种方式是最基本的实现方式,但是不支持多线程。因为没有加锁,在多线程不能正常工作# \/ W7 |! w8 {7 U/ I
//懒汉式(线程不安全)
5 a* L7 U) }# \* p9 npublic class Singleton {
8 B5 @3 N0 y. l0 v9 C; K* D private static Singleton instance; 4 u: _3 O' z+ X$ ?# I7 D1 k
# u! w3 \0 f# _ P/ Z private Singleton (){}
: J' A# B* G( b+ d' Y& Y. D7 c, h/ }& F7 ^2 G' v& L
public static Singleton getInstance() { 9 E' R/ R( W- l( W" b1 x
if (instance == null) {
/ N9 b8 w+ m; d9 Q+ i instance = new Singleton();
, o) G# L& c4 g% O! ?. s* z7 J } ) I" _9 C6 z. K+ r% c
return instance; 2 W7 b/ Y* N+ J" N, D
} & C- }3 r1 G* m$ `+ W* i: m
}
! F* n9 E4 ^4 {2、懒汉式(线程安全) 描述:能够在多线程下正常工作,但是,效率极低 //懒汉式(线程安全); [3 g0 j; ] H' L
public class Singleton { , A2 J9 p5 V6 v: A
private static Singleton instance;
! B1 m" T+ }' d
7 F. i# s9 W, E$ ]/ m private Singleton (){} " @1 H' f; o8 h$ c1 l& T; y
5 t' z1 }0 V. N7 y3 q public static synchronized Singleton getInstance() { 4 @' c. z- h. j# u ]9 ?
if (instance == null) {
2 h0 l& e' e; } instance = new Singleton();
7 A* T1 C% Y& i \3 C2 I7 n( X }
# x* C9 O2 }+ s$ U- g* y return instance; 7 m% p4 D2 t \) ? g
}
, W. i9 V/ P) |# ~2 Q# n}) m. H: z, U1 X* ], q8 F
1 I$ R1 o: D$ I. q1 w4 \; {
3、双重校验锁(DCL,即double-checked locking)(线程安全) 描述:对懒汉式(线程安全)的优化,采用双锁的机制,安全且在多线程情况下能保持高性能 ( p6 O! Y" {, F6 R+ q
//双重校验锁9 S; C% V! X2 p7 ?* ~
public class Singleton {
+ W5 I0 V$ [& a" a; e2 h private volatile static Singleton instance;
# t: X! {: y, f, ?: t% e6 s4 b: b
private Singleton() {
1 N& W9 F5 f/ c) D2 Z! o8 u4 c
$ Z7 g: M: B4 f, b3 w1 K }: H6 b( M P# j. L7 X, s
4 V+ K9 W/ i6 h* h; Z
public static Singleton getInstance() {8 @ Z3 M: M4 m- Q$ I# f
if (instance == null) {
# I0 ^5 `" g- i8 h6 M synchronized (Singleton.class) {+ G$ t4 B( E( t. y% w
if (instance == null) {( @1 D# i% l7 ]# G, e6 [
instance = new Singleton();
$ ^+ `" B2 o8 S- G# V }
$ c' E9 m Y+ R3 r8 x% ?% l- d }1 h- W. \6 k& D* b% {
}) u/ j1 I) w* i/ @1 T2 @ O7 D
return instance;
8 `0 x' p+ |% n }: K% {6 I+ _5 Q6 P
}1 |% X5 k* |7 T$ P2 q
2 A% N% b7 c5 ?+ E3 U$ {+ K" p' O- E
* N# Q& Y3 C2 C4、饿汉式(线程安全) 描述:这种方式比较常用,但容易产生垃圾对象
" f6 ?: ~. u9 _0 R- t; X//饿汉式
+ }# S- Q4 Y) ^) q$ d& G& W4 \' Rpublic class Singleton {
4 ~8 O0 G/ t$ Z& z9 a2 p private static Singleton instance = new Singleton();
' o4 k; ^2 S) r' v3 \! _3 h: f/ \
$ k3 a0 C9 h o private Singleton() {) b8 j# @1 I1 }1 [: G6 ^2 g9 |
' W2 }# A/ b; x& f W6 Z" O: {$ c; c
}( y+ ]; U/ \6 L4 q/ {- ~
" y3 R3 k& W" C8 x( r0 Y$ n( k public static Singleton getInstance() {! P A9 t% M l7 a# R8 F
return instance;
- K1 m* ]1 m# ]4 {# c }9 \2 H4 d5 G7 d8 W
}
. c6 W, p; E, u7 @" i
4 o' o1 ^- u6 l* r+ z! I' o
0 W* N0 K% h- p8 p5、静态内部类(线程安全) 描述:这种方式达到跟双重校验锁一样的效果,这种方式只适用于静态域的情况,双重校验锁可在实例域需要延迟初始化时使用 //静态内部类
3 U$ ?& x& y, t6 e& W; Y" t# Lpublic class Singleton {5 u8 x3 X1 E; v5 L+ R
private static class SingletonHolder {6 f9 @& f9 T7 ^- q7 E/ J
private static final Singleton INSTANCE = new Singleton();
2 l _$ b* r5 J# V( [ }; A! p$ | Y3 I. V
1 X8 q" Y& P( p* { private Singleton() {
: u8 ^4 G( ?( N1 M7 V/ e* |) s$ i; M/ @; w, c5 ~# a: O
} ?5 E% ~* q: h
1 N7 ~+ g" T4 u! h' I# a7 i
public static final Singleton getInstance() {
& t) L! G* s% D6 ^ return SingletonHolder.INSTANCE;8 F$ X& Q; T- h+ g* z& u, p# B
}
7 Q' f B( `: m' X! J0 U9 L}
% M# o" u" [7 {7 n% j
# k6 D, ~" [, O5 Q+ r# C6、枚举(线程安全) 描述:这种方式还没有被广泛采用,但是这种实现是单例模式的最佳方法。更简洁、自动支持序列化机制、绝对防止多次实例化
, b, c% C# }6 D' \8 K/ p//枚举) q! J( W- I8 B1 U2 I! ~# F
public enum Singleton {+ i/ z, z) ]' v7 P% y
INSTANCE;
3 X) E8 N4 I1 q/ V; {
7 s- N$ M# h* [. u2 t public void whateverMethod() {0 \+ ?& e4 }1 {; @: ]
& E' s$ H. A8 B, x2 I) y7 R
}
( o X- P- a+ q) z5 b, J* h; w}9 u3 I8 `1 \) S4 O
& R. ~; ^3 u& V u2 [6 M
$ i/ f4 e7 L2 E+ b7 ]总结
4 u- L: c3 P4 G& f: O
. R/ B* ]4 v. B4 p4 X一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第4种饿汉方式。只有在明确实现lazy loading时,才会使用第5种静态内部类方式。如果涉及到反序列化创建对象时,可以使用第6种枚举方式。如果有其他需求,可以考虑使用第3种双重校验锁方式。
5 f7 t; R$ Y7 B- ^( s5 [8 g4 R1 MPS:开始面临着春招,好多面经都有说到设计模式。最常见的面试题就是讲一讲单例模式的实现和理解,所以我写一下,加深我对单例模式的理解和印象。觉得对你有帮助的话可以点点赞,谢谢啦~~~+ E+ G; g, u, O( P0 D
————————————————8 _7 s' ~2 v' i% {* H1 w3 O
. T: B: H; J f& B" e' \5 w: F x5 Q: J( E5 t h+ u$ N2 a; E9 V1 U) g
@7 s3 y! a$ A0 N
+ R$ I+ M& [* C0 Q
( ~/ u2 y( B' j2 G3 s# [0 i
: j- V! l9 i z S9 O4 E7 ~0 P3 }( G+ N
' B3 H3 Y% n4 V& U; w. E1 _, p
8 I5 q0 Z! T B2 z8 z9 c- g4 h
原文链接:https://blog.csdn.net/weixin_37686415/article/details/105164764
3 f5 I( H4 L0 @$ s6 ~' I; Z/ C
* r0 x4 t$ |6 x W' z$ Q& K7 P' H1 ^1 g2 x0 W
|