采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的静态方法。
1. 饿汉式-静态常量
实现步骤:构造器私有化;类内部创建私有对象;向外暴露一个公共的静态方法getInstance();
优点:类装载时候就完成实例化,避免了线程同步问题。
缺点:类装载时候就完成实例化,如果从始至终未使用过这个实例,则造成内存空间浪费。
demo:
public class Singleton1 {
//类内部创建对象实例
private final static Singleton1 INSTANCE = new Singleton1();
//构造器私有化
private Singleton1(){
}
//提供给外部公共静态方法
public static Singleton1 getInstance(){
return INSTANCE;
}
}
2. 饿汉式-静态代码块(优缺点同上)
public class Singleton1 {
//类内部创建对象实例
private static Singleton1 instance;
//构造器私有化
private Singleton1() {
}
//提供给外部公共静态方法
public static Singleton1 getInstance() {
return instance;
}
static {
instance = new Singleton1();
}
public static void main(String[] args) {
Singleton1 instance1 = Singleton1.getInstance();
Singleton1 instance2 = Singleton1.getInstance();
System.out.println(instance1 == instance2);//true
}
}
3. 懒汉式
实现步骤:构造器私有化;类内部创建私有对象;向外暴露一个公共的静态方法getInstance();
优点:起到了懒加载的效果,但只能在单线程下使用。
缺点:多线程下使用会产生多个实例。
demo:
public class Singleton1 {
//类内部创建对象实例
private static Singleton1 instance;
//构造器私有化
private Singleton1() {
}
//提供给外部公共静态方法
public static Singleton1 getInstance() {
if (instance == null) {
instance = new Singleton1();
}
return instance;
}
public static void main(String[] args) {
Singleton1 instance1 = Singleton1.getInstance();
Singleton1 instance2 = Singleton1.getInstance();
System.out.println(instance1 == instance2);//true
}
}
4. 懒汉式-同步方法
实现步骤:构造器私有化;类内部创建私有对象;向外暴露一个公共的静态的同步方法getInstance();
优点:解决了线程不安全的问题。
缺点:效率太低。每个线程在想获得类的实例时候,getInstance()方法都要进行同步。
demo:
public class Singleton1 {
//类内部创建对象实例
private static Singleton1 instance;
//构造器私有化
private Singleton1() {
}
//提供给外部公共静态方法
public static synchronized Singleton1 getInstance() {
if (instance == null) {
instance = new Singleton1();
}
return instance;
}
public static void main(String[] args) {
Singleton1 instance1 = Singleton1.getInstance();
Singleton1 instance2 = Singleton1.getInstance();
System.out.println(instance1 == instance2); //true
}
}
5. 懒汉式-双重检查
实现步骤:构造器私有化;类内部创建私有对象;向外暴露一个公共的静态方法,加入双重检查代码。
优点:实现了懒加载,同时也保证了线程安全,且保证了效率。
demo:
public class Singleton1 {
//类内部创建对象实例
private static volatile Singleton1 instance;
//构造器私有化
private Singleton1() {
}
//提供给外部公共静态方法
public static Singleton1 getInstance() {
if (instance == null) {
synchronized (Singleton1.class) {
if(instance == null){
instance = new Singleton1();
}
}
}
return instance;
}
}
6. 懒加载-静态内部类
实现步骤:构造器私有化;类内部创建静态内部类,内部类中声明并实例化一个对象;提供一个公共静态方法。
优点:采用类装载的机制来保证初始化实例时只有一个线程,保证了线程安全;只有在调用getInstance()方法时才去装载静态内部类,实现了懒加载;效率高。
demo:
public class Singleton1 {
//构造器私有化
private Singleton1() {
}
//静态内部类
private static class SingletonInstance{
private static final Singleton1 INSTANCE = new Singleton1();
}
//提供公共静态方法
public static Singleton1 getInstance(){
return SingletonInstance.INSTANCE;
}
}
7. 枚举方式
实现方式:创建一个枚举类;枚举类中定义变量。
优点:避免多线程同步问题;防止反序列化重新创建新的对象。
demo:
public class Singleton2 {
public static void main(String[] args) {
Singleton instance1 = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance1 == instance2);
instance1.test();
}
}
enum Singleton {
INSTANCE;
public void test(){
System.out.println("ok");
}
}