详解JAVA 七种创建单例的方法
发布时间:2023-05-17 15:06:05
单例模式是一种常见的设计模式,它可以确保某个类只有一个实例,且该实例可以全局共享。在Java中,创建单例有多种方式,本文将详细介绍七种常见的创建单例的方法。
方法一:饿汉式(线程安全)
饿汉式是最基本的单例模式,它在类加载时就创建一个单例对象,线程安全但浪费资源。代码实现如下:
public class Singleton1 {
private static final Singleton1 INSTANCE = new Singleton1();
private Singleton1() {}
public static Singleton1 getInstance() {
return INSTANCE;
}
}
方法二:懒汉式(非线程安全)
懒汉式是最简单的一种单例模式,只有在 次调用时才创建单例对象,但是非线程安全,在多线程环境下容易出现错误。代码实现如下:
public class Singleton2 {
private static Singleton2 instance;
private Singleton2() {}
public static Singleton2 getInstance() {
if(instance==null) {
instance=new Singleton2();
}
return instance;
}
}
方法三:懒汉式(线程安全,同步方法)
为了避免懒汉式线程不安全的问题,可以使用同步方法,但是每次都要进行同步检查,效率低下。代码实现如下:
public class Singleton3 {
private static Singleton3 instance;
private Singleton3() {}
public static synchronized Singleton3 getInstance() {
if(instance==null) {
instance=new Singleton3();
}
return instance;
}
}
方法四:懒汉式(线程安全,同步代码块)
懒汉式线程安全的另一种实现方式是使用同步代码块,每次只需要检查一次就好,效率较高。代码实现如下:
public class Singleton4 {
private static Singleton4 instance;
private Singleton4() {}
public static Singleton4 getInstance() {
if(instance==null) {
synchronized (Singleton4.class) {
if(instance==null) {
instance=new Singleton4();
}
}
}
return instance;
}
}
方法五:静态内部类
静态内部类是一种优秀的单例实现方式,它利用Java的类加载机制来保证线程安全以及延迟加载。可以看做饿汉式和懒汉式的一种结合。代码实现如下:
public class Singleton5 {
private Singleton5() {}
private static class SingletonInstance{
private static final Singleton5 INSTANCE = new Singleton5();
}
public static Singleton5 getInstance() {
return SingletonInstance.INSTANCE;
}
}
方法六:枚举
枚举实现单例是一种非常优雅、简洁的方式,它保证了线程安全以及 性。代码实现如下:
public enum Singleton6 {
INSTANCE;
public void whateverMethod() {
}
}
方法七:双重校验锁
双重校验锁是一种经典的单例实现方式,它可以保证线程安全和延迟加载,但是需要注意双重校验锁的实现细节。代码实现如下:
public class Singleton7 {
private volatile static Singleton7 instance;
private Singleton7() {}
public static Singleton7 getInstance() {
if(instance==null) {
synchronized (Singleton7.class) {
if(instance==null) {
instance=new Singleton7();
}
}
}
return instance;
}
}
综上所述,以上七种方法是JAVA中创建单例的常见方式,每种方式都有其优缺点,选择合适的方式可以根据实际情况而定。需要注意的是,在使用时应该考虑到线程安全以及实例 性的问题。
