单例模式个人理解
一个类只允许创建一个对象(或者实例),那这个类一定就是单例
单例模式最大的特征就是构造器私有化,常见的饿汉式和懒汉式
先说说饿汉式,饿汉式在类加载好的时候创建了一个静态的类的实例对象,
所有的的线程都只能访问这一个对象,所以他是线程安全的
package com.wzw.single;
//饿汉式
public class Hungry {
//构造器私有化
private Hungry(){}
//饿汉式只要虚拟机启动了他就会把所有的内存空间都加载进来会浪费内存
private final static Hungry hungry=new Hungry();
public static Hungry getInstance(){
return hungry;
}
}
//饿汉式会造成内存浪费,因为只要虚拟机启动了他就会把所有的内存空间都加载进来
/*如果这个单例理由这么多对象,他一下将全部加载的话会浪费空间
Byte[] bytes=new Byte[1024*1024];
Byte[] bytes2=new Byte[1024*1024];
Byte[] bytes3=new Byte[1024*1024];
Byte[] bytes4=new Byte[1024*1024];
* */
但是他在类加载的时候就进行了初始化,如果占用资源较多,就会造成内存的浪费,所以我们就想在调动的时候才初始化,这时候我们就可以用到懒汉式
但是一般的懒汉式在方法上加锁会导致每次获得实例都要同步,开销很大,性能很低
所以就出现了双重检测模式的懒汉式单例,简称TCL
他只会在第一次初始化的时候加锁,以后不会再加锁,
而且还用volatile关键字,防止指令重排
package com.wzw.single;
//懒汉式
public class Lazy {
private Lazy() {}
private volatile static Lazy lazy;
//双重检测锁模式
public static Lazy getInstance(){
if (lazy==null){
synchronized (Lazy.class){
if(lazy==null){
lazy= new Lazy();
}
}
}
return lazy;
}
}
或者我们可以用比双重检测模式更简单静态内部类
即实现了线程安全,又防止同步带来的性能影响
package com.wzw.single;
public class LazyInner {
private LazyInner(){}
private static class LazyHolder{
private static final LazyInner lazyInner=new LazyInner();
}
public static final LazyInner getInstance(){
return LazyHolder.lazyInner;
}
}
插一嘴:上面这些方法虽然都是线程安全的,但是在反射面前他们都不是安全的,因为反射可以无视无参构造的私有化
最安全,最牛的单例应该是枚举
比如我们项目中的应用,用Map<账号,用户名>来做一个全局缓存
package com.wzw.single;
import java.util.HashMap;
import java.util.Map;
public class TestSingleton {
String name = null;
Map name1=null;
private TestSingleton() {}
private static volatile TestSingleton instance = null;
public static TestSingleton getInstance() {
if (instance == null) {
synchronized (TestSingleton.class) {
if (instance == null) {
instance = new TestSingleton();
}
}
}
return instance;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map getName1() {
return name1;
}
public void setName1(Map name1) {
this.name1 = name1;
}
public void printInfo() {
System.out.println("the name is " + name);
}
}
class Test01{
public static void main(String[] args) {
HashMap<Object, Object> map = new HashMap<>();
map.put("账号","用户名")
TestSingleton.getInstance().setName("dekudekuku");
TestSingleton.getInstance().setName1(map);
TestSingleton.getInstance().printInfo();
}
}