1、饿汉式
/**
* 饿汉式:直接创建对象,不管你是否需要,都会创建这个对象;
*
* 1、构造器私有化
* 2、自动创建,并且用静态保存
* 3、向外提供这个实例
* 4、强调这是一个单利模式,可以用final修饰
*/
public class Singleton1 {
private Singleton1(){
}
public static final Singleton1 INSTANCE = new Singleton1();
}
2、枚举
/**
* 枚举类型:表示该类型的对象是有限的几个,
* 我们定义成一个,就成了单利模式
*/
public enum Singleton2 {
INSTANCE
}
3、适用于初始化比较复杂的实例
/**
* 适用于初始化比较复杂的实例;
*/
public class Singleton3 {
public static final Singleton3 INSTANCE;
private Singleton3(){
}
static {
//此处初始化其他数据;
INSTANCE = new Singleton3();
}
}
4、懒汉式
/**
* 懒汉式:延迟创建这个实例对象;
*
* 1、构造器私有化
* 2、用一个静态变量保存这个唯一的实例;
* 3、提供一个静态方法,获取这个实例;
*/
public class Singleton4 {
private static Singleton4 instance;
private Singleton4(){
}
public static Singleton4 getInstance(){
if (instance == null){
//Thread.sleep(100);此处睡眠,若两个线程同时进入,会创建两个对象
instance = new Singleton4();
}
return instance;
}
}
/**
* 懒汉式:延迟创建这个实例对象;
*
* 1、构造器私有化
* 2、用一个静态变量保存这个唯一的实例;
* 3、提供一个静态方法,获取这个实例;
*/
public class Singleton5 {
private static Singleton5 instance;
private Singleton5(){
}
public static Singleton5 getInstance(){
synchronized (Singleton5.class){
if (instance == null){
try {
//此处睡眠,若两个线程同时进入,会创建两个对象
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
instance = new Singleton5();
}
}
return instance;
}
}
5、内部类的方式
//在内部类加载的时候才会创建对象INSTANCE
//静态内部类不会自动随着外部类的加载和初始化而初始化,他是单独去加载和初始化的;
public class Singleton6 {
private Singleton6(){
}
private static class Inner{//内部类
private static final Singleton6 INSTANCE = new Singleton6();
}
public static Singleton6 getInstance(){
return Inner.INSTANCE;
}
}
6、双端检索机制(DCL)
public class SingletonDemo2 {
public static volatile SingletonDemo2 instance = null;
private SingletonDemo2(){
System.out.println("SingletonDemo2");
}
//DCL(双端检索机制)
public static SingletonDemo2 getInstance(){//由于指令重排机制,不一定100%线程安全
if (instance == null){
synchronized (SingletonDemo2.class){
if (instance == null){
instance = new SingletonDemo2();
}
}
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
new Thread(() ->{
getInstance();
},String.valueOf(i)).start();
}
}
}