单例模式是设计模式最为常见的一种,也是面试中常常考到的。下面作为记录,希望对你也有所帮助。
推荐
- 枚举方式
- 静态内部类方式
- Double-Check方式
/**
* 单例模式:整个系统软件中,只有一个实例对象
* 枚举
* 优点:
* 达到了 lazy loading 的效果;线程安全;效率高 - 生产环境推荐使用
* 缺点:
* xx
*/
public class EunmSingletonDemo {
public static void main(String[] args) {
Singleton instance1 = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance1 == instance2);
instance1.sayHello();
}
}
enum Singleton{
INSTANCE;
public void sayHello() {
System.out.println("hi! girl ...");
}
}
/**
* 单例模式:整个系统软件中,只有一个实例对象
* 静态内部类
* 【
* 明确:
* 当静态内部类所在的外部类被加载的时候,静态内部类不会被加载。
* 当获取静态内部类的成员时,会通过类的加载初始化静态成员变量。且不会存在线程安全问题
*
* 】
* 优点:
* 达到了 lazy loading 的效果;(利用了类加载机制实例时,只有一个线程)线程安全;效率高 - 生产环境推荐使用
* 缺点:
* xx
*/
public class StaticInnerClassSingletonDemo {
public static void main(String[] args) {
StaticInnerClassSingleton instance1 = StaticInnerClassSingleton.getInstance();
StaticInnerClassSingleton instance2 = StaticInnerClassSingleton.getInstance();
System.out.println(instance1 == instance2);
}
}
class StaticInnerClassSingleton{
private StaticInnerClassSingleton(){}
//静态内部类
private static class InnerClass {
private static final StaticInnerClassSingleton SINGLETON = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance() {
return InnerClass.SINGLETON;
}
}
/**
* 单例模式:整个系统软件中,只有一个实例对象
* 懒汉式(线程安全 - 同步代码块 - Double Check)
* volatile:可以理解为轻量级的 synchronized,可以让修改地址立即更新到主存
* 优点:
* 达到了 lazy loading 的效果;线程安全;效率高 - 生产环境推荐使用
* 缺点:
* xx
*/
public class LazySingleton4Demo {
public static void main(String[] args) {
LazySingleton4 instance1 = LazySingleton4.getInstance();
LazySingleton4 instance2 = LazySingleton4.getInstance();
System.out.println(instance1 == instance2);
}
}
class LazySingleton4 {
//1.私有化构造
private LazySingleton4() {
}
//2.构造静态常量对象
private static volatile LazySingleton4 singleton;
//3.提供共有的访问方法
public static LazySingleton4 getInstance() { //double check
if (singleton == null) { //保证了效率
synchronized (LazySingleton4.class) { //解决了多线程安全问题
if (singleton == null) { //防止重复创建
singleton = new LazySingleton4();
}
}
}
return singleton;
}
}
不推荐
饿汉式
/**
* 单例模式:整个系统软件中,只有一个实例对象
* 饿汉式(静态常量)
* 优点:
* 写法简单;类加载就完成实例化;避免了线程安全问题
* 缺点:
* 没有达到 lazy loading 的效果;无论是否使用,都会加载到内存。可能会造成内存浪费
*/
public class HungrySingleton1Demo {
public static void main(String[] args) {
HungrySingleton1 instance1 = HungrySingleton1.getInstance();
HungrySingleton1 instance2 = HungrySingleton1.getInstance();
System.out.println(instance1 == instance2);
}
}
class HungrySingleton1 {
//1.私有化构造
private HungrySingleton1() {
}
//2.构造静态常量对象
private static final HungrySingleton1 SINGLETON = new HungrySingleton1();
//3.提供共有的访问方法
public static HungrySingleton1 getInstance() {
return SINGLETON;
}
}
/**
* 单例模式:整个系统软件中,只有一个实例对象
* 饿汉式(静态代码块)
* 优点:
* 写法简单;类加载就完成实例化;避免了线程安全问题
* 缺点:
* 没有达到 lazy loading 的效果;无论是否使用,都会加载到内存。可能会造成内存浪费
*/
public class HungrySingleton2Demo {
public static void main(String[] args) {
HungrySingleton2 instance1 = HungrySingleton2.getInstance();
HungrySingleton2 instance2 = HungrySingleton2.getInstance();
System.out.println(instance1 == instance2);
}
}
class HungrySingleton2 {
//1.私有化构造
private HungrySingleton2() {
}
//2.构造静态常量对象
private static HungrySingleton2 singleton;
static {
singleton = new HungrySingleton2();
}
//3.提供共有的访问方法
public static HungrySingleton2 getInstance() {
return singleton;
}
}
懒汉式
/**
* 单例模式:整个系统软件中,只有一个实例对象
* 懒汉式(线程不安全)
* 优点:
* 达到了 lazy loading 的效果;
* 缺点:
* 只能在单线程下使用,在多线程情况下,可能产生多个实例。生产环境不使用
*/
public class LazySingleton1Demo {
public static void main(String[] args) {
LazySingleton1 instance1 = LazySingleton1.getInstance();
LazySingleton1 instance2 = LazySingleton1.getInstance();
System.out.println(instance1 == instance2);
}
}
class LazySingleton1 {
//1.私有化构造
private LazySingleton1() {
}
//2.构造静态常量对象
private static LazySingleton1 singleton;
//3.提供共有的访问方法
public static LazySingleton1 getInstance() {
if (singleton == null) {
//当一个线程进来后,还未执行下面的代码;另一个线程也进来,就会产生多个实例
singleton = new LazySingleton1();
}
return singleton;
}
}
/**
* 单例模式:整个系统软件中,只有一个实例对象
* 懒汉式(线程安全 - 同步方法)
* 优点:
* 达到了 lazy loading 的效果;
* 缺点:
* 同一时间,只能有一个线程获取实例(即便已经实例化),效率低。生产环境不推荐使用
*/
public class LazySingleton2Demo {
public static void main(String[] args) {
LazySingleton2 instance1 = LazySingleton2.getInstance();
LazySingleton2 instance2 = LazySingleton2.getInstance();
System.out.println(instance1 == instance2);
}
}
class LazySingleton2 {
//1.私有化构造
private LazySingleton2() {
}
//2.构造静态常量对象
private static LazySingleton2 singleton;
//3.提供共有的访问方法
public static synchronized LazySingleton2 getInstance() { //效率低,即便只是获取(对象已经实例化)
if (singleton == null) {
singleton = new LazySingleton2();
}
return singleton;
}
}
/**
* 单例模式:整个系统软件中,只有一个实例对象
* 懒汉式(线程安全 - 同步代码块)
* 优点:
* 达到了 lazy loading 的效果;
* 缺点:
* 任然可能存在多实例情况。生产环境不推荐使用
*/
public class LazySingleton3Demo {
public static void main(String[] args) {
LazySingleton3 instance1 = LazySingleton3.getInstance();
LazySingleton3 instance2 = LazySingleton3.getInstance();
System.out.println(instance1 == instance2);
}
}
class LazySingleton3 {
//1.私有化构造
private LazySingleton3() {
}
//2.构造静态常量对象
private static LazySingleton3 singleton;
//3.提供共有的访问方法
public static LazySingleton3 getInstance() {
if (singleton == null) {
//当一个线程进来后,还未执行下面的代码;另一个线程也进来,就会产生多个实例
synchronized (LazySingleton4.class) {
singleton = new LazySingleton3();
}
}
return singleton;
}
}