概述
什么是设计模式
设计模式是前辈对代码开发经验的总结,是解决特定问题的一系列套路他不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。
设计模式的意义
设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。
单例模式
饿汉式模式
随着Java启动就加载
//饿汉式单例
public class Hungry {
// 就算没有任何地方使用这个对象,他也会创建这些数组,可能会浪费空间
private byte[] data1 = new byte[1024*10242];
private byte[] data2 = new byte[1024*10242];
private byte[] data3 = new byte[1024*10242];
private byte[] data4 = new byte[1024*10242];
//私有的构造方法防止对象被外部实例化
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
懒汉式模式
首次被使用的时候在加载
//懒汉式单例
public class LazyMan {
private LazyMan(){
System.out.println(Thread.currentThread().getName());
}
private static LazyMan lazyMan;
public static LazyMan getInstance(){
if(lazyMan==null){
lazyMan = new LazyMan();
}
return lazyMan;
}
//单线程并发
public static void main(String[] args){
for(int i =0;i<10;i++){
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}
结果:可以看出在多线程创建的情况下会创建多次这个对象
Thread-0 Thread-2 Thread-1
DCL懒汉式模式
修复并发问题
- getInstance 判断是否已经被实例化如果没有实例化进入
- getInstance 如果没有被实例化进入并且加锁防止多个线程进入进行实例化
- getInstance 为了防止A线程已经加锁成功并且成功实例化,而B线程等待锁这时A线程释放了锁
- getInstance B线程这时进入到了synchronized内部这时还需要判断是否已经实例化了
- getInstance 因为A线程已经实例化了所以B线程就不在进行实例化对象
- 防止CPU在执行实例化对象的过程中发生非原子性的问题,加上volatile关键字可以防止
//懒汉式单例
public class LazyMan {
private LazyMan(){
}
//解决返回没有没有完成构造方法和初始化的对象这个问题 加上volatile
private volatile static LazyMan lazyMan;
//双重检测所模式 懒汉式单例 DCL懒汉式
public static LazyMan getInstance(){
if(lazyMan==null){
synchronized (LazyMan.class){
if(lazyMan==null){
lazyMan = new LazyMan();//他不是一个原子性操作
/**
* 1. 分配内存空间
* 2. 执行构造方法,初始化对象
* 3. 把这个对象指向这个空间
* 正常的情况下如过走123是不是有问题的
* 但是CPU是可以会出现走132这种情况 他先分配一个空间,吧这个对象执行这个空间,最后在执行构造方法
* 如
* A 线程 执行13
* 现在B线程来使用这个对象
* 此时lazyMan已经分配了地址 但是没有执行构造方法和初始化对象
* 直接执行了return lazyMan
* 此时这个对象还不能进行使用
*/
}
}
}
return lazyMan;//返回没有没有完成构造方法和初始化的对象
}
//单线程并发
public static void main(String[] args){
for(int i =0;i<10;i++){
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}
静态内部类
package cn.qileyun.single;
//静态内部类
public class Holder {
private Holder() {
}
public static Holder getInstance(){
return InnerClass.HOLDER;
}
public static class InnerClass
{
private static final Holder HOLDER = new Holder();
}
}