什么是单例模式
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式特点:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式的八种写法
1 , 饿汉式
//饿汉式
public class Singleton {
//创建一个本类对象
private final static Singleton SINGLETON = new Singleton();
//私有化构造函数
private Singleton(){
}
//返回该对象
public Singleton getsSingleton(){
return SINGLETON;
}
}
优点:在类加载的时候,就完成实例化,避免线程并发问题.
缺点:如果一直没被使用就会造成内存浪费
2 , 懒汉式
//懒汉式
public class Singleton {
//创建一个本类对象
private static Singleton SINGLETON;
//私有化构造函数
private Singleton(){
}
//返回对象
Public static Singleton getSingleton(){
if(SINGLETON==null){
SINGLETON = new Singleton1();
}
return SINGLETON;
}
}
优点:在需要的时候才实例化
缺点:线程不安全,在多线程的状况下,可能会生成多个实例对象
3 , 懒汉式(线程安全)
//懒汉式(线程安全)
public class Singleton {
//创建一个本类对象
private static Singleton SINGLETON;
//私有化构造函数
private Singleton(){
}
//返回对象
//synchronized,使该方法为原子性,不被多个线程同时执行
public static synchronized Singleton getSingleton(){
if(SINGLETON==null){
SINGLETON = new Singleton();
}
return SINGLETON;
}
}
优点:解决了线程不安全问题
缺点:效率过低,每个线程在调用getSingleton()方法都需要等待先调用该方法的线程完成,才能调用.
4 , 懒汉式(提高效率,但线程不安全)
public class Singleton {
//创建一个本类对象
private static Singleton SINGLETON;
//私有化构造函数
private Singleton(){
}
//返回对象
public static Singleton getSingleton(){
if(SINGLETON==null){
//只锁住实例化对象语句
synchronized(Singleton.class){
SINGLETON = new Singleton();
}
}
return SINGLETON;
}
}
优点:提高了效率,在调用getSingleton()方法的时候,进入同步代码块中.
缺点:线程不安全,依然有可能实例化多个对象
6 , 懒汉式(线程安全并且提高了效率)
public class Singleton {
//创建一个本类对象
private static Singleton SINGLETON;
//私有化构造函数
private Singleton(){
}
//返回对象
public static Singleton getSingleton(){
if(SINGLETON==null){
synchronized(Singleton.class){
if(SINGLETON==null){
SINGLETON = new Singleton();
}
}
}
return SINGLETON;
}
}
优点:通过双重检查,保证了是线程安全的,并且实例化代码只执行了一次.
7 , 静态内部类
//静态内部类
public class Singleton {
//私有化构造函数
private Singleton(){
}
//静态内部类
private static class SingletonInstance{
private static final Singleton SINGLETON = new Singleton();
}
public static Singleton getSingleton(){
return SingletonInstance.SINGLETON;
}
}
这种方法和饿汉式的原理一样,也是采用了类装载的机制来保证初始化实例时只有一个线程,不同之处在于:饿汉式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
8 , 枚举
//枚举类
public enum Singleton {
INSTANCE;
public static void main(String[] args) {
Singleton singleton = Singleton.INSTANCE;
}
}