浅谈单例模式的实现方式
) k; l! t% N* S+ p7 P单例模式(来自菜鸟教程)! D9 g; N/ s+ Y
4 ^$ u5 ]" \5 f5 |4 p M. k单例模式(Singleton Pattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
9 E; H- T' g e# p, S: K单例模式的要求
j. u+ F- L5 F& ^6 g( G! a6 N- A' `% E2 S' x6 H
构造方法必须私有化(确保只有自己能创建)) N5 f" A2 ? x" i& v+ H
以静态方法返回实例(外界不能通过new来获取到对象) b. H+ e" V$ m
确保对象实例只有一个(只对类进行一次实例化,以后都直接获取第一次实例化的对象)
0 i- O& {: f" m( |5 c单例模式的实现
. {+ K9 p( k0 @" a7 j, H' U7 I# v% @/ Q9 P2 c6 S W# y
1、懒汉式(线程不安全)4 a/ D9 v' y8 A7 M% X
* }, v% y3 H3 R8 r
描述:这种方式是最基本的实现方式,但是不支持多线程。因为没有加锁,在多线程不能正常工作
( d) t( W1 Y d2 f7 k//懒汉式(线程不安全)
# z0 m5 x) h) p5 e$ upublic class Singleton {
9 E" b. y' V5 |2 h2 O private static Singleton instance; z5 z) z* X! a6 B) w2 k5 M# V2 N
+ R, o K5 i( M% e private Singleton (){} 6 |5 u& A: r% B3 ?" {
% V+ D3 q$ I# J, s3 [6 \% b public static Singleton getInstance() { 5 A/ B5 j) h$ g. |! P, r: \7 }
if (instance == null) {
6 U1 O; }0 ~* I8 | instance = new Singleton();
7 H( O2 U' r* A } 1 R, A" u/ O% V7 }
return instance;
* m+ v# I/ H" q# I: e }
7 a% z1 {9 t g4 V. Q}# y, y" r* _6 b5 n
2、懒汉式(线程安全) 描述:能够在多线程下正常工作,但是,效率极低 //懒汉式(线程安全)
" ?, q9 O `- W: gpublic class Singleton { 5 d m; Z# ]# U! F" e: F
private static Singleton instance;
1 s4 c. o2 k% n$ o: {# n- Z1 E" J
" V- m. c+ c9 d+ k& @0 P private Singleton (){}
. P0 e. a; z0 Z8 A( { f+ {( S. z% a& n9 v
public static synchronized Singleton getInstance() { F0 w$ B1 X8 T- h
if (instance == null) { * O. r k7 A3 |" P) e
instance = new Singleton(); & l* K# w3 P+ q8 J* C
} 2 B" h9 s+ b6 |5 {! I* W+ u
return instance;
3 |0 Z5 }( ~3 v7 }5 Z9 d }
$ S5 ~' |4 R+ o0 ]+ L' u2 x4 o. @# n! L}% t9 d6 n ?2 o- g6 ]+ I" v
, z# h% c1 D7 [9 L8 _8 Z3、双重校验锁(DCL,即double-checked locking)(线程安全) 描述:对懒汉式(线程安全)的优化,采用双锁的机制,安全且在多线程情况下能保持高性能
) x( S/ x3 Q' g$ y, }( X A//双重校验锁 f3 X$ o L7 n1 g- R2 F
public class Singleton {
4 i/ \1 R3 Q/ F" D private volatile static Singleton instance;. g, v9 Y$ I. b; v9 m- Z9 g
' _) d7 M8 I6 |$ i5 F& O# l
private Singleton() {
- d4 Q G. }4 P( n2 C2 k/ E
' Q: R( M' R5 Q" A/ v3 ? }
2 L, Q) k: j1 t% A
$ L1 J0 _1 I, | [0 O3 z public static Singleton getInstance() {, t: W( t' \" M8 U
if (instance == null) {
5 K6 X0 R" b* o. M }8 ^ synchronized (Singleton.class) {
5 e8 k5 W' N U if (instance == null) {
% X) w, c' ^9 |- S5 \, K instance = new Singleton();
2 `) Z6 a6 a6 ? }
l. }+ }+ l2 Z8 k/ s$ | }1 m; O- P+ A% ?) p) \( K& S
}
3 I4 W# C) p7 y/ D return instance;
6 Y, H, l m8 _ }$ s! g1 n# ~. {* m! u- `: `! Q
}$ M5 ^+ D, n( `
( k1 ]- [ l0 w q
+ e* w7 {4 X( b" c
4、饿汉式(线程安全) 描述:这种方式比较常用,但容易产生垃圾对象 7 B4 M D- {8 {, j4 B$ \2 c
//饿汉式! r. Q: [7 m3 [4 @' u
public class Singleton {
/ \* K" F6 c( c9 ~- S. y private static Singleton instance = new Singleton();6 D8 l- O0 E2 E3 ]. m
# V" z# S g1 i8 D9 V$ G private Singleton() {
- u7 g% V% t& S8 v+ ?2 P
1 n- K/ S$ e' S9 U3 @: g* N* ] }
4 ]# i! K( z! ]
3 X/ g1 N) u: b public static Singleton getInstance() {- |' q# C( Z+ |3 M+ j3 g
return instance;0 X, u3 x' n3 R, X! t2 a" Z
}' s! t! x- g0 g" ^0 o( ]' s
}
- p9 y) R1 t, m
% L# ]5 L& t1 P. U" v% a; h$ s/ \
, w0 L4 E' D2 ?* ]$ n5、静态内部类(线程安全) 描述:这种方式达到跟双重校验锁一样的效果,这种方式只适用于静态域的情况,双重校验锁可在实例域需要延迟初始化时使用 //静态内部类- l. n7 o. i/ B6 D" H: g
public class Singleton {
* K3 v( ^6 i3 ~7 ~+ _. T private static class SingletonHolder {
! Q9 |! r3 p4 ^- F private static final Singleton INSTANCE = new Singleton();' [/ U2 z5 K# U: T3 P3 K
}
( d' e$ W) C& t) g7 P/ ]; Z8 ]& S" l; R! ]/ A
private Singleton() {/ L% ]. ^: l4 |* m! c5 h
! \# O' }* u# V5 r* W- b; _6 T }
7 p8 V% e3 H+ ^3 `' N u
( I* F& U" I0 E public static final Singleton getInstance() {
) ^' u: v6 m0 W+ j' e return SingletonHolder.INSTANCE;
* W* F6 f4 A( K- S! u8 l; d }
) a4 v/ e% Q7 {# {6 m- F}
- H$ J2 C( ?3 i$ y6 F; s
" z0 F' Y: r1 _6、枚举(线程安全) 描述:这种方式还没有被广泛采用,但是这种实现是单例模式的最佳方法。更简洁、自动支持序列化机制、绝对防止多次实例化 , c9 E0 u& k0 m* G
//枚举
2 ]) |& F) w: y3 x! |1 Kpublic enum Singleton {
# Y- h6 G) b" W9 D: b! U, e3 @# n INSTANCE;' p8 [7 o/ _/ y
) z2 o `. b* G7 J
public void whateverMethod() {
; U* s8 b6 L0 Y: Y; d
' _& z5 f0 R8 J' z: U$ \ }$ w0 E0 u9 H, n" q2 ^2 k- d& X
}
) ]7 F. ]6 `' L; U, w
, i; n2 z3 c" D# m% _# C4 X. B5 u |. K a4 T
总结+ d+ |0 s/ u" N: J
2 k) }. o0 d7 h: [一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第4种饿汉方式。只有在明确实现lazy loading时,才会使用第5种静态内部类方式。如果涉及到反序列化创建对象时,可以使用第6种枚举方式。如果有其他需求,可以考虑使用第3种双重校验锁方式。
7 ~8 S$ l7 \# {) W2 |; UPS:开始面临着春招,好多面经都有说到设计模式。最常见的面试题就是讲一讲单例模式的实现和理解,所以我写一下,加深我对单例模式的理解和印象。觉得对你有帮助的话可以点点赞,谢谢啦~~~
# _" ^2 ` Z3 W1 t————————————————
) x( P' g& x# c% `2 q, J# }- M
( S% D: s3 D+ n% |* r: l: ~8 g8 D% [' ]2 ?
* H7 r0 |- m* I& ]/ y" x
( P8 L; ?( Z4 J) b
V) y3 ~1 g" [8 u. M3 Q
A" k' ~$ @, E/ _6 d9 M
5 I* C1 `$ ]/ J/ _5 w
5 x3 j, _! Z) Z
# S a& O% ]0 [& @原文链接:https://blog.csdn.net/weixin_37686415/article/details/105164764
$ i; A* Z; o* T
6 l" X5 z+ V4 O! i, S7 f" g6 x8 J3 X' t$ B* E
|