众所周知,一般使用java实现单例模式有两种方法,分别为饿汉式和饱汉式,饿汉式就是在声明时即创建,这样在类加载时就已经创建好了,即时我们可能并不不需要它,它的生命周期是永久的,造成内存泄漏的可能!第二种方式是lazy的,只有在使用时创建,实现了延迟加载。代码为
1.饿汉式
1
2
3
4
5
6
7
8
|
class
Singleton {
private
final
static
Singleton instance =
new
Singleton();
private
Singleton(){
}
public
static
Singleton getInstance() {
return
instance;
}
}
|
2. 饱汉式(双重加锁式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class
Singleton {
private
volatile
static
Singleton instance =
null
;
private
Singleton(){
}
public
static
Singleton getInstance() {
if
(instance ==
null
) {
synchronized
(Singleton.
class
) {
if
(instance ==
null
) {
instance =
new
Singleton();
}
}
}
return
instance;
}
}
|
还有一种方法是使用内部类的方法,这主要为克服方法1中的问题,既能实现延迟加载,又能保证线程安全,而且性能不错。代码为:
1
2
3
4
5
6
7
8
9
10
11
|
class
Singleton {
private
Singleton() {
}
private
static
class
Holder {
private
static
final
Singleton INSTANCE =
new
Singleton();
}
public
static
Singleton getInstance() {
return
Holder.INSTANCE;
}
}
|
以上方法都是通过使用private构造方法来阻止外部直接创建对象,但如果使用反射机制,则不能保证实例的唯一性了!!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public
class
SingletonDemo {
//@SuppressWarnings("unchecked")
//public static <T> T newInstance(Class<?> cl) {
// T t = null;
// try {
// t = (T)cl.newInstance(); /* 只能调用public构造方法 */
// } catch(Exception e) {
// e.printStackTrace();
// }
// return t;
//}
@SuppressWarnings
(
"unchecked"
)
public
static
<T> T newInstance(Class<?> cl) {
T t =
null
;
try
{
Constructor<?> constructor = cl.getDeclaredConstructor();
constructor.setAccessible(
true
);
t = (T)constructor.newInstance();
}
catch
(Exception e) {
e.printStackTrace();
}
return
t;
}
@SuppressWarnings
(
"unchecked"
)
public
static
<T> T newInstance(Class<?> cl, Class<?>...args) {
T t =
null
;
try
{
Constructor<?> constructor = cl.getDeclaredConstructor(args);
constructor.setAccessible(
true
);
t = (T)constructor.newInstance(
"name"
,
1
);
}
catch
(Exception e) {
e.printStackTrace();
}
return
t;
}
public
static
void
main(String[] args) {
Singleton instance = Single.INSTANCE;
Singleton s1 = newInstance(Singleton.
class
, String.
class
,
int
.
class
);
Singleton s2 = newInstance(Singleton.
class
, String.
class
,
int
.
class
);
//Tmp t1 = newInstance(Tmp.class);
//Tmp t2 = newInstance(Tmp.class);
//System.out.println(s1 == s2);
//System.out.println(t1 == t2);
}
}
|
Joshua Bloch (Effect java 作者)提出一种新的方法实现单例模式,就是使用Enum(其实也是类,一种特殊的类,构造方法必须是private ,final的)!如下:
1
2
3
4
5
6
|
enum
Singleton {
INSTANCE;
public
void
sayHi() {
System.out.println(
"Hi"
);
}
}
|
这样当试图通过反射机制创建对象时,会抛出异常!