浅谈单例模式的实现方式( G0 V2 q! t! R2 C/ M! _" h. O
单例模式(来自菜鸟教程)/ W, u8 ?. [3 e
. @# P& a' |" m
单例模式(Singleton Pattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。9 F- @$ n. V" f; g2 n
单例模式的要求0 g+ N8 \2 T+ ~: @- P1 \2 U
+ E% t7 V2 H5 q4 I& p* P构造方法必须私有化(确保只有自己能创建)4 [7 r7 R7 m0 r7 x0 M- }
以静态方法返回实例(外界不能通过new来获取到对象)
- R, }( k' @6 p P确保对象实例只有一个(只对类进行一次实例化,以后都直接获取第一次实例化的对象)
9 H* [3 s6 f! g$ [2 l% H5 b单例模式的实现
) b1 p& B, v2 X+ g4 ?& ^4 f( ~: v, v6 \
1、懒汉式(线程不安全) C7 C7 x: ]; j2 k2 {4 d5 }
5 o2 D- n" Q. a" n9 t# L描述:这种方式是最基本的实现方式,但是不支持多线程。因为没有加锁,在多线程不能正常工作
. v: A6 [" m% s# C }; [0 D//懒汉式(线程不安全)0 o4 v- a* j+ Z k& D/ u& Q
public class Singleton { M! T( Y& q M6 p) P+ N" d
private static Singleton instance;
+ f* t( B$ A7 x' D) j3 I
9 {* v$ J2 T: N5 q private Singleton (){} {/ t0 n5 X6 `9 U/ ~# Y( e
" ?0 _# E5 f1 |5 }) N- f
public static Singleton getInstance() { % J4 a& [8 [& [, p8 C' e
if (instance == null) { ; q" a0 a4 M; B. J
instance = new Singleton(); % y5 g+ ]- Y0 L2 ]% k8 k5 y4 N
} % S9 g( Z, n2 z* H$ @
return instance; - v5 g, y" M; [& x, I# R8 A- C+ a
} ! c* u* h3 y# z5 M
}
6 {# y T( B( }$ P2、懒汉式(线程安全) 描述:能够在多线程下正常工作,但是,效率极低 //懒汉式(线程安全)
6 x4 K% Q; ]5 @) Npublic class Singleton { , t# Y( c! f7 g" z6 b
private static Singleton instance; ) ~+ ~* U" b* F
6 ~5 F, S" r" G
private Singleton (){} ) }8 J! N) r( N
8 E9 ]: W9 x; t+ p
public static synchronized Singleton getInstance() { . r- [/ k( J m ^' z
if (instance == null) { ) F4 W# ]6 F( d0 V
instance = new Singleton();
9 n! s3 e1 A) x$ S } : x8 u- U8 Y5 ?. ]! V2 `7 ^
return instance; J+ a+ ]' B& L/ q
}
4 \9 O& W7 e! K2 T s+ U: b# b}: Z, h! Z3 e+ Q! d$ u( n6 z
: D4 K: ]9 L: r3、双重校验锁(DCL,即double-checked locking)(线程安全) 描述:对懒汉式(线程安全)的优化,采用双锁的机制,安全且在多线程情况下能保持高性能
7 M& r3 i* y t# m1 _//双重校验锁
+ t% q& s0 a3 q- v. Npublic class Singleton {
{4 {1 m1 p2 J private volatile static Singleton instance;
! S1 C9 x3 t( ?* \4 x# r* O/ z3 V8 g: x" N: u' v
private Singleton() {7 t$ Z9 e" l- @
& A8 X% y. k' Z; R( }
}- s( z# H( R2 Z; O4 e3 {
4 s9 J: p J. v x' ~
public static Singleton getInstance() {
( b% L& V& ^7 G0 M7 b& m' V$ j if (instance == null) {7 [2 t) y% L% w) g% M/ y* l$ |
synchronized (Singleton.class) {
+ h. }, C6 s: Y if (instance == null) {
" k& F& T0 |# e y* p7 C' D e instance = new Singleton();
7 A3 ?/ m8 |4 f" v; T4 Q( Z }1 I5 X# K# S K; T2 r
}
$ n3 \/ f: n& Y x3 ~ }
& l6 e3 A' T# ]2 z return instance;
' I% a4 P: l) s* P; u }
; Y( c& u( _) r3 J/ W, }' _}
6 }* e3 F6 x# t8 b& V/ l$ A0 |1 w/ R* m7 w0 |+ t( a% Q0 _2 h& ?. r
' d6 G5 h2 S$ A. S
4、饿汉式(线程安全) 描述:这种方式比较常用,但容易产生垃圾对象
/ f$ N, ]: Z( s4 B5 [- n/ L//饿汉式 K4 H$ O: p$ t) J, b! }; _4 |: r
public class Singleton {9 V- O' ?" H, l9 b4 v4 p( B/ p
private static Singleton instance = new Singleton();
8 ^2 K) x4 f$ r' D" ` t R8 r( h. i! g, ~! j
private Singleton() {
4 }& \# D. c2 ?# U7 F* b9 w4 `% j$ A
}) ]: R! h r+ C5 |) t
! K. k8 _, t. x; o4 f9 b) J
public static Singleton getInstance() {3 \3 c5 G3 E# X/ \& V
return instance;
' x0 i* d. {/ z+ v5 I }
4 ^5 O( I' h6 q- \) T- w}3 c' E7 e& V2 y. M& v0 T9 D. t# P1 D% n
7 |/ B. U H. |& {& M; [8 M6 d) g5 F2 Q' a6 O4 p
5、静态内部类(线程安全) 描述:这种方式达到跟双重校验锁一样的效果,这种方式只适用于静态域的情况,双重校验锁可在实例域需要延迟初始化时使用 //静态内部类
7 h: |* t9 g. i# T! K( K/ j' ypublic class Singleton {
! I9 R$ \) A4 V/ y+ _+ u private static class SingletonHolder {
' G9 P9 W$ Q$ r% X, K5 ] | private static final Singleton INSTANCE = new Singleton();# f: \4 W6 W, Z; K P" f! P
}& Z! @: y! v9 Z1 v- F- f
l! G5 {7 k; L) ^) v! R private Singleton() {
5 ?! x8 j, C. ?2 D
+ y S6 h; e5 F4 y; f/ Z }3 P. w) g1 e1 @8 d6 {
5 S, `7 p% @: e; b
public static final Singleton getInstance() {
2 j3 ~$ \ @% p1 k9 J1 I/ U return SingletonHolder.INSTANCE;: k8 R1 ]( O* U+ E1 l
}. v( b7 @$ N: y' V6 u Q
}
( B8 S. B* D( o+ K$ v( X# J; p& U5 h2 G$ L$ C% s @" `
6、枚举(线程安全) 描述:这种方式还没有被广泛采用,但是这种实现是单例模式的最佳方法。更简洁、自动支持序列化机制、绝对防止多次实例化 3 n( c% p5 h& j/ w
//枚举
. {- v3 @) k% h9 V8 M2 wpublic enum Singleton {5 `, c) R4 N6 @
INSTANCE;
. J0 \: A/ P! ?4 a9 a5 o' L! f3 ?- n3 Z% j6 @
public void whateverMethod() {$ z9 E/ ]$ T& A
- Z! I1 O8 p# u& D6 q$ q
}
N6 M0 W$ y3 G% w}1 `% I/ X- Y; o) [5 \
; V6 D; ]9 Q; ?* r+ ?' J
; r- `, g U) B; f) ]3 W总结
( ? v4 f$ H5 ~0 P8 }1 B# |9 E0 W! M! X5 D
一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第4种饿汉方式。只有在明确实现lazy loading时,才会使用第5种静态内部类方式。如果涉及到反序列化创建对象时,可以使用第6种枚举方式。如果有其他需求,可以考虑使用第3种双重校验锁方式。
: X- p4 [$ G4 q- p# R+ u9 }PS:开始面临着春招,好多面经都有说到设计模式。最常见的面试题就是讲一讲单例模式的实现和理解,所以我写一下,加深我对单例模式的理解和印象。觉得对你有帮助的话可以点点赞,谢谢啦~~~% j% p' y9 Y3 l7 S
————————————————
; @% {- W( W: \" C Z) V
. \* p9 |9 f! j$ g2 w4 S- B) @8 ?9 x, }2 |9 u
2 j9 Q4 r/ _8 W: a
. c0 X( |9 w0 C O K
1 v" u4 d ]) i# A0 D% M: c
# ^! }4 u- S! H' Y% |5 t" I5 T. ]1 N6 J) R# P
7 Q5 ^/ Q# ?( i. T8 j$ a) h% N9 V
% ?1 `2 o: ^' {' c) I' y0 p
原文链接:https://blog.csdn.net/weixin_37686415/article/details/105164764
O$ K* W5 _% O, R- p
3 j ?# m3 C% [
+ w5 U' F9 |! J7 @; ?1 E |