单例模式
单例模式(Singleton)的定义:一个类只能有一个实例,并且这个实例由这个类创建。在软件设计中,为了节约空间、保证数据的一致性,许多类只能拥有一个实例,这种设计就采用单例模式。单例模式的实现方法是:1、使类的构造方法私有化;2、创建属于此类类型的静态成员对象;3、提供静态方法获取对象。
单例模式的实现
常用的单例模式的实现方式有4种,其中包括懒汉式、饿汉式、枚举实现、双重检测方式,下面进行介绍。
饿汉式
该方式的特点是在加载类的时候就创建对象,此种方式是线程安全的。但是在类的创建过程复杂、繁琐时,这种方式导致类的加载过于缓慢。
/**
* 单例模式饿汉式
*/
public class Singleton {
private static final Singleton instance = new Singleton() ;
private Singleton(){}
public static Singleton getInstance(){
try {
Thread.sleep(3000); //模拟创建延迟
} catch (InterruptedException e) {
e.printStackTrace();
}
return instance;
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(()->{
ints1 = Singleton.getInstance();
});
Thread thread2 = new Thread(()->{
ints2 = Singleton.getInstance();
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(ints1 == ints2);
System.out.println(ints1);
System.out.println(ints2);
}
}
枚举方式
这种方式有点和饿汉式一样,都是简单实现,同时是线程安全的。
// 枚举实现方式
public enum SingletonEnum {
Instance();
SingletonEnum getInstance(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Instance;
}
}
//测试类
public class Singleton {
private static SingletonEnum inst1;
private static SingletonEnum inst2;
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(()->{
inst1 = SingletonEnum.getInstance();
});
Thread thread2 = new Thread(()->{
inst2 = SingletonEnum.getInstance();
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(inst1 == inst2);
System.out.println(inst1);
System.out.println(inst2);
}
}
懒汉式
这种方式的特点是在需要第一次需要对象的时候加载类。为了保证线程安全,对实例对象使用volatile关键字,同时在获取实例对象的方法上使用synchronized关键字。这种方式的缺点是在方法上加锁过于频繁,其实只需要在第一次创建对象的时候需要将方法加锁,而后面获取对象的操作是不需要加锁的,这样会降低效率。
/**
* 单例模式懒汉式
*/
public class Singleton {
private static volatile Singleton instance = null;
private static Singleton ints1;
private static Singleton ints2;
private Singleton(){}
public static synchronized Singleton getInstance(){
try {
Thread.sleep(3000); //模拟创建延迟
} catch (InterruptedException e) {
e.printStackTrace();
}
if(instance == null){
instance = new Singleton();
}
return instance;
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(()->{
ints1 = Singleton.getInstance();
});
Thread thread2 = new Thread(()->{
ints2 = Singleton.getInstance();
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(ints1 == ints2);
System.out.println(ints1);
System.out.println(ints2);
}
}
双重检测方式
这种方式是改造懒汉式创建方式,只在第一次创建时加锁,后面获取实例不用加锁便能获取对象,改善了获取类的效率。
**
* 单例模式双重检测方式
*/
public class Singleton {
private static volatile Singleton instance = null;
private static Singleton ints1;
private static Singleton ints2;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
synchronized (Singleton.class){
if(instance == null){
try {
Thread.sleep(3000); //模拟创建延时
} catch (InterruptedException e) {
e.printStackTrace();
}
instance = new Singleton();
}
}
}
return instance;
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(()->{
ints1 = Singleton.getInstance();
});
Thread thread2 = new Thread(()->{
ints2 = Singleton.getInstance();
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(ints1 == ints2);
System.out.println(ints1);
System.out.println(ints2);
}
}