浅谈单例模式的实现方式
1 v \, j; O2 w& @6 h# p$ ]单例模式(来自菜鸟教程)
5 \5 x( B2 J2 n9 k. D
8 S1 ^( Q- ^: S1 {单例模式(Singleton Pattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。2 C2 \$ o, J5 h$ T) {& N
单例模式的要求/ e/ T+ q$ h( N" F: e4 z- `. [- \
1 S/ O- W+ y' ^6 [- ]构造方法必须私有化(确保只有自己能创建)
" U3 T3 v1 @" x- C7 S) i7 g以静态方法返回实例(外界不能通过new来获取到对象)
7 h6 R4 i5 {9 R6 L. {) V% R确保对象实例只有一个(只对类进行一次实例化,以后都直接获取第一次实例化的对象)
" J, _6 j' W0 N单例模式的实现% W% f- c" y8 P( S
2 O) J& i% X% f
1、懒汉式(线程不安全)
) U$ t" d# T+ D% W5 {
7 [8 i$ t" x% T! ?1 u描述:这种方式是最基本的实现方式,但是不支持多线程。因为没有加锁,在多线程不能正常工作
* C. i6 Q* K2 u: p//懒汉式(线程不安全)! M" v2 P8 ~3 q& G
public class Singleton {
9 A5 [ b5 |1 l+ @0 e0 X private static Singleton instance; : f7 J3 a9 V( ?* d% d% Z8 U _; B; G
# b. m) Z& I \" R/ }' z
private Singleton (){}
' y" G0 T8 t0 H0 r+ G
& m% Y/ G1 k8 u" @ public static Singleton getInstance() { : Q& u. \9 K, C' M$ F- ?
if (instance == null) { . O' x" Y T# K8 q* G
instance = new Singleton(); : g9 u t' t0 |- {. j( q
}
: O9 j" T2 a1 a" Z1 M/ t return instance; 7 J" a2 z m3 l# D3 M. g& o
} 6 J E2 U% k5 o' Y. L* G6 ]6 [( Z
}
0 s+ M3 e$ u; b( `5 E! I# G2、懒汉式(线程安全) 描述:能够在多线程下正常工作,但是,效率极低 //懒汉式(线程安全)
" ?* ?4 j# u8 Ppublic class Singleton {
' S2 k0 v: Z1 p9 T: i/ }( J private static Singleton instance;
7 a2 i: P4 M$ w- P: Y% U
: J! H, x, P# ?" o! t# b# f private Singleton (){}
9 V2 d( Y' X: L/ q' E+ G0 [7 c9 Y; O) T2 P8 @# { Z6 l5 A
public static synchronized Singleton getInstance() { . `$ r D' ^* M& a
if (instance == null) {
& z. O& t9 n: v( X% B' W. L) z instance = new Singleton();
* M) E+ Y4 A" X! A: K }
% F) m$ r2 a9 p9 a0 ^" q return instance;
, \9 e( I* \4 l7 F/ J j }
8 z0 Q* \" ~" O6 N7 r* t( f}9 r% Y* Y2 D. ~1 R9 Z4 O* B
8 B; {! ]8 A8 d$ `: k3、双重校验锁(DCL,即double-checked locking)(线程安全) 描述:对懒汉式(线程安全)的优化,采用双锁的机制,安全且在多线程情况下能保持高性能 9 a9 b& Q- k6 U6 ~+ |
//双重校验锁
* L s0 T2 R( M2 kpublic class Singleton {. t8 `$ m; i- l, P7 d
private volatile static Singleton instance;+ g! H1 ]; \+ [
2 \4 b, s' t* b, w# T8 y6 @
private Singleton() {1 k8 N# j& s/ i2 B5 a1 x% p
. @: D: S2 l* V' O- p
}; a0 U: {* U" |
, c; ^* U6 C3 U4 d. P9 ` public static Singleton getInstance() {! b3 E( K/ ^0 e5 }
if (instance == null) {
9 z8 F+ S2 S4 k$ B( r synchronized (Singleton.class) {. \# P$ F2 j# b* Q- `* @
if (instance == null) {
" n. {( j8 g* f& O0 f instance = new Singleton();) o3 |/ y5 _+ }3 Y
}4 @2 ]# n! m; p
}1 b! E1 q* k/ b- y" a$ E3 w
}1 I0 P6 z! N, }9 X, |% R6 m
return instance;
3 e! r- D2 U R q# @ e }0 o0 g4 e; M% V) p1 \$ E+ O; m
}7 T% L0 {4 B) P# Z
, E% |* O1 h; I' Q s4 C( M
t+ j& J2 F$ C) |# E0 v9 j6 K4、饿汉式(线程安全) 描述:这种方式比较常用,但容易产生垃圾对象 * N" [3 ]9 W+ |% j
//饿汉式
5 J# B- Q4 B' upublic class Singleton {
5 O' M9 [$ I6 B7 t6 l private static Singleton instance = new Singleton();
6 ^, q9 H# W, F0 ?
- o. m& h, Q+ g* F private Singleton() {+ n' u0 l5 _6 }( i- @ S7 E9 |
- |* p9 X8 o5 _; u }2 ?' `. S" }! o+ R! s3 C# [
& u1 M$ B5 N$ Q. w B G% @! |
public static Singleton getInstance() { Q7 G% l2 e6 @ l( M
return instance;) Y$ \5 ?; ]* C4 ~9 m2 w
}
5 v" V/ _( K6 v: o& N8 \" a}+ X* p- N( Y7 }8 u- i
/ {2 @) Y) T+ K( l. J$ T2 a8 o y, p
: x6 ~9 [- I7 T. E5、静态内部类(线程安全) 描述:这种方式达到跟双重校验锁一样的效果,这种方式只适用于静态域的情况,双重校验锁可在实例域需要延迟初始化时使用 //静态内部类
+ F: Y- c6 k7 y) |/ ~public class Singleton {
1 R- Z: O. _* P/ [# W1 w+ A+ s private static class SingletonHolder {- }+ c. A ~4 t$ u
private static final Singleton INSTANCE = new Singleton();3 d( u4 F9 X7 d' |7 v4 J
}% J" d# h! T5 c$ u
* Z' `) t' f2 S2 E2 ^
private Singleton() {
* T( Z. E8 }6 A6 _
( S. ~( T# b' }+ U }
- V4 |6 W5 a1 u0 {0 f, i4 V! K- D9 _- B- @7 b6 u% u
public static final Singleton getInstance() {
1 C1 I! ^/ i: ?1 _' e3 C8 }7 m8 K return SingletonHolder.INSTANCE;' `- ^+ @1 R( c$ s
}1 p7 K5 g) W5 z( e# f/ p0 U
}
4 j8 _! B; J5 ]: {% g4 E' p9 p& w% e7 I! O
6、枚举(线程安全) 描述:这种方式还没有被广泛采用,但是这种实现是单例模式的最佳方法。更简洁、自动支持序列化机制、绝对防止多次实例化
% n* Y+ m5 S( r5 b# G* e3 N% P//枚举6 x4 N4 `$ @! N" D0 @
public enum Singleton {; h: \* ]% n i8 C9 d2 z
INSTANCE;, W) u Q% O5 t) Y
* Q' W& Z% g3 w+ s public void whateverMethod() {
5 B/ x# n) }. U" _ ?' ~9 d+ e
9 _, {3 h( e! } }6 j" E! J$ P1 P* P
}
- X' N6 I |8 n
, B( F/ y W+ H3 t; i
& @$ [) k' }" z; L# ]( o4 J总结
$ E# a1 j% ~% M8 @" h9 S7 S
( D& y' b! y/ J& n r8 H一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第4种饿汉方式。只有在明确实现lazy loading时,才会使用第5种静态内部类方式。如果涉及到反序列化创建对象时,可以使用第6种枚举方式。如果有其他需求,可以考虑使用第3种双重校验锁方式。' V) B9 V' |) |2 P! H+ c& _
PS:开始面临着春招,好多面经都有说到设计模式。最常见的面试题就是讲一讲单例模式的实现和理解,所以我写一下,加深我对单例模式的理解和印象。觉得对你有帮助的话可以点点赞,谢谢啦~~~
, p/ I9 C4 f- C4 A5 K3 K! e————————————————
0 s/ b! u2 Y2 D+ n6 |+ f' ?; b! T$ U
& o9 |5 J# _! Y# F
: [0 k- `! T) ?) F( x6 p3 e* _: [6 |
5 c& i. v% w, K7 u. X; N% F
$ K1 J0 I. ]9 ~! z
2 \8 d8 J6 D" d/ f4 i8 \9 b" l* N
) e# V, @2 Y A7 O2 J1 T
1 t2 b1 F$ U2 F4 ]9 l
! u3 Q T; t5 ], K8 E7 X原文链接:https://blog.csdn.net/weixin_37686415/article/details/105164764
5 |0 a; ?) k) Q) P2 Z4 o- j& e- [( M3 b$ n/ |/ T$ Q
. V) [. J# ? h9 |) T8 e q5 I* ?3 T |