(实现方法按照由易至杂,由好到坏排列)
solution1:
/**
* Created by Bob on 15/9/27.
*/
public class Singleton {
private static Singleton instance = null;
public static Singleton getInstance() {
if (instance== null){
instance= new Singleton();
}
return instance;
}
}
点评:
只适用于单线程,当两个线程同时同时运行到判断语句时,就会产生重复创建实例的情况。如果不加说明,就是错误的答案
solution2:
class Singleton1{
private static Singleton1 instance= null;
public static synchronized Singleton1 getInstance(){
if (instance== null){
instance= new Singleton1();
}
return instance;
}
}
点评:
此种方法适合于多线程,但是效率一般。将getInstance方法写成同步方法,
这样在线程1进入之后,其他线程都被阻塞在方法外边。这样当线程1发现instance为null时,
就会创建一个实例。方法执行结束后,就会释放该临界区,此时其他线程再占用此临界区时,
就不会再次重复创建了。然而,同步锁的加持和释放是一个非常耗时的操作。
solution3:
public static Singleton getInstance2() {
if (instance == null) {
synchronized (new Object()) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
点评:
我们就只在instance为空的时候进行加锁操作
如果后续线程在锁外边判断为空的时候,才进行加锁操作,
当然啦,锁是唯一的,只有当该临界区的锁被释放之后,猜可能进行新的加锁操作
避免了在instance不为空的时候,进行的加锁,释放锁的繁琐操作
solution4:
public static Singleton getInstance(){
return Nested.instance;
}
static class Nested{
static Singleton instance= new Singleton();
}
点评:
使用了静态内部,当第一次调用的时候,Nested内部类才会被调用,
而它是一个静态的对象,随着Nested被调用而初始化,真正做到了被调用时才初始化,且具有对象的唯一性
extra:
/**
* 使用同步代码块缩小临界区来提高效率
*通过只保护需要同步保护的部分来减小临界区大小
* @return
*/
public static Singleton1 newInstance(){
synchronized (new Object()){
if (instance== null){
instance= new Singleton1();
}
}
return instance;
}
/**
* 使用互斥锁来达到目的,这里就不使用try...finally了
*/
private static Lock lock;
public static Singleton1 getInstance1() {
lock.lock();
if (instance== null){
instance= new Singleton1();
}
lock.unlock();
return instance;
}