单例模式有很多的变种,饿汉模式变化不大不多说
非线程安全的懒汉模式
public class LazySingletonDemo {
private static LazySingletonDemo instance;
public static LazySingletonDemo getInstance() {
if (instance == null) {
instance = new LazySingletonDemo();
}
return instance;
}
}
线程安全的懒汉模式
这种情况使用场景不是很多,除非特殊的情况下,假如只是单纯的作为工具类或者存放常量这种作用的话,考虑多线程安全没有太大意义,多new出来的对象失去引用很快会被GC掉,除非一瞬间并发量爆炸,同时new了超多的对象(真遇到了那得放鞭炮)
1.使用synchronized
public class LazySingletonDemo {
private static LazySingletonDemo instance;
public static LazySingletonDemo getInstance() {
System.out.println(Thread.currentThread().getName() + " 1");
if (instance == null) {
System.out.println(Thread.currentThread().getName() + " 2");
synchronized (LazySingletonDemo.class) {
System.out.println(Thread.currentThread().getName() + " 3");
if (instance == null) {
System.out.println(Thread.currentThread().getName() + " 4");
instance = new LazySingletonDemo();
}
}
}
return instance;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
LazySingletonDemo.getInstance();
}
};
Thread t1 = new Thread(r, "t1");
Thread t2 = new Thread(r, "t2");
Thread t3 = new Thread(r, "t3");
Thread t4 = new Thread(r, "t4");
Thread t5 = new Thread(r, "t5");
Thread t6 = new Thread(r, "t6");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
输出
t1 1
t6 1
t6 2
t3 1
t3 2
t4 1
t4 2
t2 1
t6 3
t5 1
t1 2
t5 2
t6 4
t2 2
t5 3
t2 3
t1 3
t4 3
t3 3
可以看出,6个线程都进入了第1,2,3步骤,但是进入到new的步骤4只有一个线程
这里不把锁放到方法上的原因是,每次拿实例的时候都要锁,非常影响性能,而只有开头new的时候才需要锁
2.使用Lock
public class LazySingletonDemo {
private static LazySingletonDemo instance;
private static ReentrantLock lock = new ReentrantLock();
public static LazySingletonDemo getInstance() {
System.out.println(Thread.currentThread().getName() + " 1");
if (instance == null) {
System.out.println(Thread.currentThread().getName() + " 2");
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + " 3");
if (instance == null) {
System.out.println(Thread.currentThread().getName() + " 4");
instance = new LazySingletonDemo();
}
} finally {
System.out.println(Thread.currentThread().getName() + " 5");
lock.unlock();
}
}
return instance;
}
public static void main(String[] args) throws InterruptedException {
Runnable r = new Runnable() {
public void run() {
LazySingletonDemo.getInstance();
}
};
Thread t1 = new Thread(r, "t1");
Thread t2 = new Thread(r, "t2");
Thread t3 = new Thread(r, "t3");
Thread t4 = new Thread(r, "t4");
Thread t5 = new Thread(r, "t5");
Thread t6 = new Thread(r, "t6");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
输出
t1 1
t3 1
t6 1
t6 2
t4 1
t4 2
t2 1
t6 3
t3 2
t5 1
t5 2
t1 2
t6 4
t2 2
t6 5
t4 3
t4 5
t3 3
t3 5
t5 3
t5 5
t1 3
t1 5
t2 3
t2 5
同上
至于Synchronized和Lock的区别就不说了,网上都有