什么是单例;
个人理解 单例单例就是单个实例,单例模式就是想办理最后只创建一个实例。这就是最终的目的。
理解了这句话之后我们可以真实开启下面的内存单例模式与多线程
1. 立即加载/“恶汉模式”
就是在调用方法前,实例已经创建了
来看测试代码
MyObject
public class MyObject {
private static MyObject myObject = new MyObject();
private MyObject() {
}
public static MyObject getInstance() {
return myObject;
}
}
MyThread
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
Run
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
运行结果
2. 延迟加载/“懒汉模式”
延迟加载就是调用get()方法时实例才被创建,常见的实现办法就是在get()方法中进行new实例化。
不考虑多线程的情况下实现懒汉式单例模式代码如下
MyObject
public class MyObject {
private static MyObject myObject;
private MyObject() {
}
public static MyObject getInstance() {
if (myObject != null) {
} else {
myObject = new MyObject();
}
return myObject;
}
}
MyThread
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
Run
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
}
}
运行结果如下
此实验虽然取得一个对象的实例,但如果实在多线程的环境中,就会出现取出多个实例的情况,与单例模式的初衷是相背离的。
a.针对上述问题使用DCL双检查锁机制
创建演示项目singleton_2
MyObject
public class MyObject {
private volatile static MyObject myObject;//多线程可见性
private MyObject() {
}
//使用双检测机制来解决问题,既保证了不需要同步代码的异步执行性
//又保证了单例的效果
public static MyObject getInstance() {
try {
if (myObject != null) {
} else {
Thread.sleep(3000);
synchronized (MyObject.class) {
if(myObject == null){
myObject = new MyObject();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
MyThread
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
Run
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
运行结果
DCL也是大多数多线程结合单例模式使用的解决方案
b.使用静态内置类实现单例模式
MyObject
public class MyObject {
private static class MyObjectHandler {
private static MyObject myObject = new MyObject();
}
private MyObject() {
}
public static MyObject getInstance() {
return MyObjectHandler.myObject;
}
}
MyThread
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(MyObject.getInstance().hashCode());
}
}
Run
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
运行结果
c.使用static代码块实现单例模式
MyObject
public class MyObject {
private static MyObject instance = null;
private MyObject() {
}
static {
instance = new MyObject();
}
public static MyObject getInstance() {
return instance;
}
}
MyThread
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(MyObject.getInstance().hashCode());
}
}
}
Run
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
运行结果
d. 使用enum枚举数据类型实现单例模式
MyObject
public class MyObject {
public enum MyEnumSingleton {
connectionFactory;
private Object object;
private MyEnumSingleton() {
object = new Object();
}
public Object getConnectin() {
return object;
}
}
public Object getConnection() {
return MyEnumSingleton.connectionFactory.getConnectin();
}
}
MyThread
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(MyObject.MyEnumSingleton.connectionFactory.getConnectin().hashCode());
}
}
}
Run
public class Run {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
运行结果