一、前言
- 单例模式注意事项和细节说明:
- 单例模式 保证了 系统内存中 只存在一个对象,节省了系统资源,对于一些需要频繁创建和销毁对象的场景下,提高了系统的性能。
- 应用场景:比如 数据源、Session 工厂 等。
二、分类:
三、代码实现:
2.1、饿汉式(静态常量):
package type01;
public class SinglctonDemo {
public static void main(String[] args) {
Singlcton singlcton1 = Singlcton.getInstance();
Singlcton singlcton2 = Singlcton.getInstance();
System.out.println(singlcton1 == singlcton2);
System.out.println("singlcton1.hashCode = "+singlcton1.hashCode());
System.out.println("singlcton2.hashCode = "+singlcton2.hashCode());
}
}
class Singlcton {
private Singlcton(){
}
private final static Singlcton instance = new Singlcton();
public static Singlcton getInstance(){
return instance;
}
}
优缺点说明:
- 优点:这种写法比较简单,就是在类加载时实例化,避免了线程同步问题。
- 缺点:在类加载时实例化,没有实现 Lazy Loading (懒加载)效果,可能未使用该实例,导致内存的浪费。
总结:这种单例模式可用,可能造成内存浪费。
2.2、饿汉式(静态代码块):
package type01;
public class SinglctonDemo {
public static void main(String[] args) {
Singlcton singlcton1 = Singlcton.getInstance();
Singlcton singlcton2 = Singlcton.getInstance();
System.out.println(singlcton1 == singlcton2);
System.out.println("singlcton1.hashCode = "+singlcton1.hashCode());
System.out.println("singlcton2.hashCode = "+singlcton2.hashCode());
}
}
class Singlcton {
private Singlcton(){
}
static {
instance = new Singlcton();
}
private static Singlcton instance;
public static Singlcton getInstance(){
return instance;
}
}
优缺点说明:
- 优点:这种写法比较简单,就是在类加载时实例化,避免了线程同步问题。
- 缺点:在类加载时实例化,没有实现 Lazy Loading (懒加载)效果,可能未使用该实例,导致内存的浪费。
总结:这种单例模式可用,可能造成内存浪费。
2.3、懒汉式(线程不安全):
package type01;
public class SinglctonDemo {
public static void main(String[] args) {
Singlcton singlcton1 = Singlcton.getInstance();
Singlcton singlcton2 = Singlcton.getInstance();
System.out.println(singlcton1 == singlcton2);
System.out.println("singlcton1.hashCode = "+singlcton1.hashCode());
System.out.println("singlcton2.hashCode = "+singlcton2.hashCode());
}
}
class Singlcton {
private Singlcton(){
}
private static Singlcton instance;
public static Singlcton getInstance(){
if(instance == null){
instance = new Singlcton();
}
return instance;
}
}
优缺点说明:
- 优点:实现 Lazy Loading (懒加载)效果,存在线程不安全问题。
- 缺点:不能在多线程的情况下使用,存在线程不安全问题。
总结:在实际开发中,不能使用这种方式。
2.4、懒汉式(线程安全、同步方法):
package type01;
public class SinglctonDemo {
public static void main(String[] args) {
Singlcton singlcton1 = Singlcton.getInstance();
Singlcton singlcton2 = Singlcton.getInstance();
System.out.println(singlcton1 == singlcton2);
System.out.println("singlcton1.hashCode = "+singlcton1.hashCode());
System.out.println("singlcton2.hashCode = "+singlcton2.hashCode());
}
}
class Singlcton {
private Singlcton(){
}
private static Singlcton instance;
public static synchronized Singlcton getInstance(){
if(instance == null){
instance = new Singlcton();
}
return instance;
}
}
优缺点说明:
- 优点:实现 Lazy Loading (懒加载)效果,解决了线程不安全问题。
- 缺点:效率太低了,每个线程都需要排队等待获取实例。
总结:在实际开发中,不能使用这种方式。
2.5、懒汉式(线程安全、同步代码块):
package type01;
public class SinglctonDemo {
public static void main(String[] args) {
Singlcton singlcton1 = Singlcton.getInstance();
Singlcton singlcton2 = Singlcton.getInstance();
System.out.println(singlcton1 == singlcton2);
System.out.println("singlcton1.hashCode = "+singlcton1.hashCode());
System.out.println("singlcton2.hashCode = "+singlcton2.hashCode());
}
}
class Singlcton {
private Singlcton(){
}
private static Singlcton instance;
public static Singlcton getInstance(){
if(instance == null){
synchronized(Singlcton.class) {
instance = new Singlcton();
}
}
return instance;
}
}
优缺点说明:
- 优点:实现 Lazy Loading (懒加载)效果,存在线程不安全问题。
- 缺点:存在线程不安全问题。
总结:在实际开发中,不能使用这种方式。
2.6、双重检查(Double-Check):
package type01;
public class SinglctonDemo {
public static void main(String[] args) {
Singlcton singlcton1 = Singlcton.getInstance();
Singlcton singlcton2 = Singlcton.getInstance();
System.out.println(singlcton1 == singlcton2);
System.out.println("singlcton1.hashCode = "+singlcton1.hashCode());
System.out.println("singlcton2.hashCode = "+singlcton2.hashCode());
}
}
class Singlcton {
private Singlcton(){
}
private static volatile Singlcton instance;
public static Singlcton getInstance(){
if(instance == null){
synchronized(Singlcton.class) {
if(instance == null) {
instance = new Singlcton();
}
}
}
return instance;
}
}
优缺点说明:
- 优点:线程安全;延时加载;效率较高。
- 缺点:暂无
总结:在实际开发中,推荐使用这种方式。
2.7、静态内部类:
package type01;
public class SinglctonDemo {
public static void main(String[] args) {
Singlcton singlcton1 = Singlcton.getInstance();
Singlcton singlcton2 = Singlcton.getInstance();
System.out.println(singlcton1 == singlcton2);
System.out.println("singlcton1.hashCode = "+singlcton1.hashCode());
System.out.println("singlcton2.hashCode = "+singlcton2.hashCode());
}
}
class Singlcton {
private Singlcton(){
}
private static class SinglctonInstance{
private final static Singlcton INSYANCE = new Singlcton();
}
public static Singlcton getInstance(){
return SinglctonInstance.INSYANCE;
}
}
优缺点说明:
- 优点:静态属性类加载使得JVM保证了线程安全问题,并且 延时加载;效率较高。
- 缺点:暂无
总结:强烈推荐使用这种方式。
2.8、枚举:
package type01;
public class SinglctonDemo {
public static void main(String[] args) {
Singlcton singlcton1 = Singlcton.INSYANCE;
Singlcton singlcton2 = Singlcton.INSYANCE;
System.out.println(singlcton1 == singlcton2);
System.out.println("singlcton1.hashCode = "+singlcton1.hashCode());
System.out.println("singlcton2.hashCode = "+singlcton2.hashCode());
}
}
enum Singlcton {
INSYANCE;
}
优缺点说明:
- 优点:借助1.5的新特性解决了线程安全问题,并且 延时加载;效率较高。
- 缺点:暂无
总结:官方强烈推荐使用这种方式。
• 由 ChiKong_Tam 写于 2020 年 10 月 16 日