1.单例模式 是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
单例模式的主要有以下角色
单例设计模式分类两种:
饿汉式:类加载就会导致该单实例对象被创建
懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建
package com.jmj.pattern.singleton.demo02;
/**
* 饿汉式 :静态代码块
*/
public class Singleton {
private Singleton(){
}
//声明Singleton类型的变量
private static Singleton singleton ;
//在静态代码块中进行复制
static {
singleton=new Singleton();
}
public static Singleton getInstance(){
return singleton;
}
}
package com.jmj.pattern.singleton.demo01;
/**
* 饿汉式 :静态成员 变量
*/
public class Singleton {
//1.私有构造方法
private Singleton(){};
//2.在本类中创建本类对象
private static Singleton singleton =new Singleton();
//3.提供一个公共的访问方式,让那个外界获取该对象
public static Singleton getInstance(){
return singleton;
}
}
线程安全
package com.jmj.pattern.singleton.demo03;
/**
* 懒汉式 线程不安全
*/
public class Singleton {
private Singleton(){}
private static Singleton singleton;
//对外提供访问方式
public static synchronized Singleton getInstance(){
if (singleton==null){
singleton=new Singleton();
return singleton;
}
return singleton;
}
}
双重检查锁
package com.jmj.pattern.singleton.demo04;
/**
* 懒汉式 双重检查锁方式
*/
public class Singleton {
private Singleton(){}
private static volatile Singleton singleton;
//对外提供访问方式
public static Singleton getInstance(){
//第一次判断,如果instance的值不为null ,不需要抢占锁,直接返回对象
if(singleton==null){
synchronized (Singleton.class){
if (singleton==null){
singleton=new Singleton();
}
}
}
return singleton;
}
}
静态内部类方式
枚举
package com.jmj.pattern.singleton.demo07;
import java.io.*;
/**
* 测试使用反射破坏单例模式
*/
public class Client {
public static void main(String[] args) throws Exception {
// writeObject2File();
readObject2File();
readObject2File();
}
//从文件读取数据(对象)
public static void readObject2File() throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("src/main/resources/static/a.txt"));
Singleton singleton = (Singleton) objectInputStream.readObject();
System.out.println(singleton);
//释放资源
objectInputStream.close();
}
//向文件中写数据 (对象)
public static void writeObject2File() throws Exception {
Singleton instance = Singleton.getInstance();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("src/main/resources/static/a.txt"));
objectOutputStream.writeObject(instance);
objectOutputStream.close();
}
}
package com.jmj.pattern.singleton.demo07;
import java.io.Serializable;
/**
* 懒汉式 匿名内部类
*/
public class Singleton implements Serializable {
private Singleton(){}
/**
* 静态内部类,只会被 在调用里面属性或者 方法的时候,才会被类加载
* 类加载的时候才加载 ,final 修饰 不会被修改
*/
private static class SingletonHolder{
private static Singleton singleton =new Singleton();
}
//对外提供访问方式
public static Singleton getInstance(){
return SingletonHolder.singleton;
}
}
反射破坏单例模式
package com.jmj.pattern.singleton.demo08;
import java.io.Serializable;
/**
* 懒汉式 匿名内部类
*/
public class Singleton {
private Singleton(){}
/**
* 静态内部类,只会被 在调用里面属性或者 方法的时候,才会被类加载
* 类加载的时候才加载 ,final 修饰 不会被修改
*/
private static class SingletonHolder{
private static Singleton singleton =new Singleton();
}
//对外提供访问方式
public static Singleton getInstance(){
return SingletonHolder.singleton;
}
}
package com.jmj.pattern.singleton.demo08;
import java.lang.reflect.Constructor;
/**
* 测试使用反射破坏单例模式
*/
public class Client {
public static void main(String[] args) throws Exception {
//1.获取Singleton的字节码对象
Class singletonClass = Singleton.class;
Constructor declaredConstructor = singletonClass.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
Singleton singleton = declaredConstructor.newInstance(null);
Singleton singleton1 = declaredConstructor.newInstance(null);
Singleton singleton2 = declaredConstructor.newInstance(null);
System.out.println(singleton);
System.out.println(singleton1);
System.out.println(singleton2);
}
}
序列化反序列化破坏单例模式解决方案
package com.jmj.pattern.singleton.demo07;
import java.io.Serializable;
/**
* 懒汉式 匿名内部类
*/
public class Singleton implements Serializable {
private Singleton(){}
/**
* 静态内部类,只会被 在调用里面属性或者 方法的时候,才会被类加载
* 类加载的时候才加载 ,final 修饰 不会被修改
*/
private static class SingletonHolder{
private static Singleton singleton =new Singleton();
}
//对外提供访问方式
public static Singleton getInstance(){
return SingletonHolder.singleton;
}
public Object readResolve(){
return SingletonHolder.singleton;
}
}
反射破解单例模式解决方案:
首先加个静态变量做标志位,然后 在构造里加锁,锁字节码对象,构造方法就被 加了同步锁了
Runtime 源码就是饿汉式单例模式
package com.jmj.pattern.singleton.demo09;
import java.io.IOException;
import java.io.InputStream;
public class RuntimeDemo {
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
long l = runtime.freeMemory();
System.out.println(l);
//要的是一个命令
Process exec = runtime.exec("ipconfig");
//调用process对象
InputStream inputStream = exec.getInputStream();
byte[] bytes = new byte[1024 * 1024 * 1024];
int len = inputStream.read(bytes);
String s = new String(bytes,0,len,"GBK");
System.out.println(s);
}
}
它的作用可以使用Java操作操作系统