目录
什么是单例,单例有什么作用
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
代码展示
单例创建的方式有八种:
- 饥汉式两种 : 静态变量单例,静态代码块单例
- 懒汉式四种 : 懒汉式(线程不安全单例),懒汉式(线程安全,同步方法单例),懒汉式(线程安全,同步代码块),懒汉式(线程安全,双重检测)
- 静态内部类单例
- 枚举单例
静态变量单例:
/**
* 饿汉式(静态变量)
* 好处:
* 写法简单,比较方便,再类加载的时候就完成了装载,避免了同步问题
* 坏处:
* 再类加载的时候就会完成装载,达不到延迟加载的效果,如果这个类一直没有使用,就会造成内存的浪费
* 总结:
* 可以使用这种方式,但是有可能造成内存的浪费
*/
public class Singleton {
//私有化构造器,防止外部new
private Singleton(){
}
// 内部创建对象实例
private final static Singleton singleton = new Singleton();
// 设置公用方法获取对象
public static Singleton getInstance(){
return singleton;
}
}
静态代码块单例:
/**
* 饿汉式(静态代码块)
* 好处:
* 写法简单,比较方便,再类加载的时候就完成了装载,避免了同步问题
* 坏处:
* 再类加载的时候就会完成装载,达不到延迟加载的效果,如果这个类一直没有使用,就会造成内存的浪费
* 总结:
* 可以使用这种方式,但是有可能造成内存的浪费
*/
public class Singleton1 {
//私有化构造器,防止外部new
private Singleton1() {
}
// 内部创建对象实例
private static Singleton1 singleton;
static {
singleton = new Singleton1();
}
// 设置公用方法获取对象
public static Singleton1 getInstance() {
return singleton;
}
}
懒汉式(线程不安全单例):
/**
* 懒汉式(线程不安全)
* 好处:
* 可以达到延迟加载,但是只能再单线程的情况使用
* 坏处:
* 再多线程的情况下,如果有3个线程abc a进入了if判断对象是否存在还没有结束的时候,b也进去了,那么就会创建多个对象,就不是单例模式了
* 总结:
* 可以达到延迟加载的效果,但是线程不安全,不建议再实际项目中使用
*/
public class Singleton2 {
//私有化构造器,防止外部new
private Singleton2() {
}
// 内部创建对象实例
private static Singleton2 singleton;
// 设置公用方法获取对象
public static Singleton2 getInstance() {
if (null ==singleton){
singleton = new Singleton2();
}
return singleton;
}
}
懒汉式(线程安全,同步方法单例):
/**
* 懒汉式(线程安全,同步方法)
* 好处:
* 可以达到延迟加载,解决了线程问题
* 坏处:
* 如果多个线程执行这个方法就会造成,一个对象多个线程来调用判断这样会影响效率
* 总结:
* 可以达到延迟加载的效果,但是影响效率,不建议再实际项目中使用
*/
public class Singleton3 {
//私有化构造器,防止外部new
private Singleton3() {
}
// 内部创建对象实例
private static Singleton3 singleton;
// 设置公用方法获取对象 添加同步代码 确保方法有对象执行的时候,其他操作不能执行
public static synchronized Singleton3 getInstance() {
if (null ==singleton){
singleton = new Singleton3();
}
return singleton;
}
}
懒汉式(线程安全,同步代码块):
/**
* 懒汉式(线程安全,同步代码块)
* 好处:
* 可以达到延迟加载,但是只能再单线程的情况使用
* 坏处:
* 再多线程的情况下,如果有3个线程abc a进入了if判断对象是否存在还没有结束的时候,b也进去了,那么就会创建多个对象,就不是单例模式了
* 总结:
* 可以达到延迟加载的效果,线程安全,但是只能再单线程的情况使用,不建议再实际项目中使用
*/
public class Singleton4 {
//私有化构造器,防止外部new
private Singleton4() {
}
// 内部创建对象实例
private static Singleton4 singleton;
// 设置公用方法获取对象 添加同步方法 确保方法有对象执行的时候,其他操作不能执行
public static Singleton4 getInstance() {
if (null == singleton) {
synchronized (Singleton4.class) {
singleton = new Singleton4();
}
}
return singleton;
}
}
懒汉式(线程安全,双重检测):
/**
* 懒汉式(线程安全,双重检测)
* 好处:
* 可以达到延迟加载,线程安全,效率高
* 总结:
* 可以达到延迟加载的效果,线程安全,建议再实际项目中使用
*/
public class Singleton5 {
//私有化构造器,防止外部new
private Singleton5() {
}
// 内部创建对象实例
//volatile
//1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
//2)禁止进行指令重排序。
private static volatile Singleton5 singleton;
// 设置公用方法获取对象 添加同步方法 确保方法有对象执行的时候,其他操作不能执行
public static Singleton5 getInstance() {
if (null == singleton) {
synchronized (Singleton5.class) {
if (null == singleton) {
singleton = new Singleton5();
}
}
}
return singleton;
}
}
静态内部类单例:
/**
* 静态类内部类
* 好处:
* 通过静态内部类加载,做到了延迟加载的效果,同时保证了线程的安全,效率比较高,代码比较简洁
* 总结:
* 推荐使用
*/
public class Singleton6 {
//私有化构造器,防止外部new
private Singleton6() {
}
// 静态内部类
private static class Singleton6Instanse{
private static final Singleton6 SINGLETON_6 = new Singleton6();
}
// 公用获取对象实例
public static Singleton6 getInstance(){
return Singleton6Instanse.SINGLETON_6;
}
}
枚举单例:
/**
* 枚举
* 好处:
* 线程安全,还能防止反序列化 ,Effective java || josh Bloch 作者推荐使用的
* 总结:
* 推荐使用
*/
public enum Singleton7 {
INSTANCE;
public void getInstance(){
System.out.println("我是枚举单例");
}
}
源码使用地址
JDK 中 Runtime 使用的就是饥汉式静态变量单例
总结
/**
* 单例模式
* 总结:
* 创建单例模式的方法有八种 Singleton,Singleton1,Singleton2,Singleton3,Singleton4
* 推荐使用三种 Singleton5,Singleton6,Singleton7
* 使用的场景:需要频繁的进行创建和销毁的对象,创建时耗时过多的或者消耗资源过多的的对象,经常使用的
* 工具对象,频繁访问数据库或文件的
* 的对象(数据源,sessionFactory)
*/