概念
终极奥义:该类负责创建自己的对象,同时确保只有单个对象被创建。
特点:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
优缺点和应用场景
优点:
- 避免频繁对象的创建和销毁,减少内存开销。
- 避免对资源的多重占用(比如写文件操作)。
缺点:
- 没有接口,不能继承,与单一职责原则冲突。
应用场景:
- 创建的一个对象需要消耗的资源过多,IO流操作文件或者是数据库连接
- spring的bean默认加载方式
几种可用的创建方式
静态常量(饿汉式)
public class SingletonOne {
private static final SingletonOne SINGLETON=new SingletonOne(); //静态常量
private SingletonOne(){}
public static SingletonOne getSingleton() {
return SINGLETON;
}
}
静态代码块(饿汉式)
public class SingletonTwo {
private static SingletonTwo singletonTwo;
static {
singletonTwo=new SingletonTwo(); //静态代码块
}
private SingletonTwo() {
}
public static SingletonTwo getSingletonTwo() {
return singletonTwo;
}
}
双重检测(懒汉式)
public class SingletonThree {
private static volatile SingletonThree singletonThree;
private SingletonThree() {
}
public static SingletonThree getSingletonThree() {
if(singletonThree==null){
synchronized (SingletonThree.class){
if(singletonThree==null){
singletonThree= new SingletonThree();
}
}
}
return singletonThree;
}
}
静态内部类(类似于饿汉式,但是实现懒加载)
public class SingletonFour {
private SingletonFour() {
}
public static class Singleton{
private static final SingletonFour singletonFour=new SingletonFour();
}
public static SingletonFour getSingletonFour(){
return Singleton.singletonFour;
}
}
枚举
public class SingletonFive {
private SingletonFive() {
}
public static SingletonFive getSingletonFive(){
return Singleton.Instance.getSingletonFive();
}
private enum Singleton{
Instance;
private SingletonFive singletonFive;
Singleton(){
singletonFive=new SingletonFive();
}
public SingletonFive getSingletonFive() {
return singletonFive;
}
}
}
实现测试(对象相等其对应的hashcode一定相等)
public class MutiThread extends Thread {
public void run() {
//int hashCode = SingletonOne.getSingleton().hashCode();
//int hashCode = SingletonTwo.getSingletonTwo().hashCode();
//int hashCode = SingletonThree.getSingletonThree().hashCode();
//int hashCode = SingletonFour.getSingletonFour().hashCode();
int hashCode = SingletonFive.getSingletonFive().hashCode();
System.out.println("hashCode:"+hashCode);
}
}
public class Test {
public static void main(String[] args) {
Thread[] threads=new Thread[10];
for(int i=0;i<threads.length;i++){
threads[i]=new MutiThread();
}
for(int i=0;i<threads.length;i++){
threads[i].start();
}
}
}
测试效果:
注意:饿汉式天生就是线程安全,类加载机制,线程在进入之前已经有对象产生。
spring里bean单例模式测试
<bean id="user" class="spring.bean.User" scope="singleton">
<property name="userId" value="wangmaoyu_prom"/>
<property name="userName" value="李大爷"/>
<property name="dept" ref="dept"/>
</bean>
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = applicationContext.getBean("user", User.class);
User user1 = applicationContext.getBean("user", User.class);
System.out.println(user+"=="+user1+":"+(user==user1)); //spring bean默认的方式
System.out.println(user.getDept().getDeptName());
}
}
效果: