单例模式
立即加载/饿汉模式
/**
* 立即加载
*/
class MyObject {
private static MyObject object = new MyObject();
private MyObject() {
}
public static MyObject getInstance() {
return object;
}
}
class MyThread implements Runnable {
@Override
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new MyThread());
thread.start();
}
}
}
延迟加载/懒汉模式
第一版
存在不支持多线程问题
class MyObject {
private volatile static MyObject object;
private MyObject() {
}
public static MyObject getInstance() {
try {
if (Optional.ofNullable(object).isEmpty()) {
// 模拟创建对象之前准备工作
Thread.sleep(3000);
object = new MyObject();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return object;
}
}
第二版
方法加关键字synchronized
,存在效率低问题
class MyObject {
private volatile static MyObject object;
private MyObject() {
}
synchronized public static MyObject getInstance() {
try {
if (Optional.ofNullable(object).isEmpty()) {
// 模拟创建对象之前准备工作
Thread.sleep(3000);
object = new MyObject();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return object;
}
}
第三版
针对某些重要的部分单独同步,存在不支持多线程问题
class MyObject {
private volatile static MyObject object;
private MyObject() {
}
public static MyObject getInstance() {
try {
if (Optional.ofNullable(object).isEmpty()) {
// 模拟创建对象之前准备工作
Thread.sleep(3000);
synchronized (MyObject.class) {
object = new MyObject();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return object;
}
}
最终版
使用DCL双检测锁机制
/**
* 延迟加载
*/
class MyObject {
private volatile static MyObject object;
private MyObject() {
}
// 双检测机制
public static MyObject getInstance() {
try {
if (Optional.ofNullable(object).isEmpty()) {
// 模拟创建对象之前准备工作
Thread.sleep(3000);
synchronized (MyObject.class) {
if (Optional.ofNullable(object).isEmpty()) {
object = new MyObject();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return object;
}
}
class MyThread implements Runnable {
@Override
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new MyThread());
thread.start();
}
}
}
网友评论