单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。
特点:
单例类只能有一个实例。
单例类必须自己创建出这个实例
单例类必须给所有其他的对象提供这一个实例
要保证单例,需要做以下几步:
必许防止外部可以调用构造函数进行实例化,因此构造函数必须被私有化。
必须定义一个静态方法 获得该类的对象。
使用synchronized进行同步处理,并且双重判断是否为null,如下面的第二个。
有状态和无状态的对象区别
基本概念:
有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象.不能保存数据,是不变类,是线程安全的。
来源: https://www.cnblogs.com/xubiao/p/6567349.html
单例模式
线程问题,在获取单例的时候,不能产生多个实例对象。还有,在使用单例对象的时候,要注意单例对象的实例变量是会被多线程共享的。推荐使用 无状态的对象(上面有简单介绍),不会因为多个线程交替调度而破坏自身状态导致的问题。
实现单例模式的方式
1. 饿汉式单例(立即加载方式)
// 饿汉式单例 public class Singleton1 { // 私有构造 private Singleton1() {} private static Singleton1 single = new Singleton1(); // 静态工厂方法 public static Singleton1 getInstance() { return single; } }
饿汉式单例在类加载初始化的时候就创建好了一个静态的对象供外部使用,除非系统重启,这个对象不会改变,所以本身就是线程安全的。
2. 懒汉式单例(演示加载方式)
// 懒汉式单例 public class Singleton2 { // 私有构造 private Singleton2() {} private static Singleton2 single = null; public static Singleton2 getInstance() { if(single == null){ single = new Singleton2(); } return single; } }
该示例虽然用延时加载方式实现了懒汉式单例,但是在多线程环境下会产生多个single对象,如何改造请看以下方式:
使用synchronized 同步锁
public class Singleton3 { // 私有构造 private Singleton3() {} private static Singleton3 single = null; public static Singleton3 getInstance() { // 等同于 synchronized public static Singleton3 getInstance() synchronized(Singleton3.class){ // 注意:里面的判断是一定要加的,否则出现线程安全问题 if(single == null){ single = new Singleton3(); } } return single; } }
在方法上加synchronized 同步锁或是同步代码块对类加同步锁,此种方式虽然解决了多个实例对象的问题,但是该方式运行效率却很低下,下一个线程想要获取对象,就必须等待上一个线程释放锁之后,才可以运行。
进行优化:
public class Singleton4 { // 私有构造 private Singleton4() {} private static Singleton4 single = null; // 双重检查 public static Singleton4 getInstance() { if (single == null) { synchronized (Singleton4.class) { if (single == null) { single = new Singleton4(); } } } return single; } }
3. 静态内部类实现
public class Singleton6 { // 私有构造 private Singleton6() {} // 静态内部类 private static class InnerObject{ private static Singleton6 single = new Singleton6(); } public static Singleton6 getInstance() { return InnerObject.single; } }
4. 静态代码块的实现
public class Singleton6 { // 私有构造 private Singleton6() {} private static Singleton6 single = null; // 静态代码块 static{ single = new Singleton6(); } public static Singleton6 getInstance() { return single; } }