参考:https://blog.csdn.net/liu_da_da/article/details/125425561
一、什么是单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
二、单例的几种实现方式
1.饿汉模式
饿汉式,就是“比较饿”,实例在初始化的时候就要创建好,不管你有没有用到。类加载到内存后,就实例化一个单例,JVM保证线程安全;简单实用,推荐实用!唯一缺点:不管用到与否,类装载时就完成实例化(话说你不用的,你装载它干啥)
public class Singleton {
private static final Singleton INSTANCE=new Singleton();
private Singleton(){};
public static Singleton getInstance(){return INSTANCE;}
}
测试用例:
public static void main(String [] args){
Singleton m1=Singleton.getInstance();
Singleton m2=Singleton.getInstance();
System.out.println(m1==m2);
}
测试结果:true
2.懒汉模式
懒汉式就是“比较懒”,就是在用到的时候才去检查有没有实例,如果有则直接返回,没有则新建。案例中保留性能与线程安全的双重检索模式。
2.1双重检索模式
//双重检索模式
public class Singleton {
private static Singleton INSTANCE2;
private Singleton(){};
public static Singleton getInstance2(){
if(INSTANCE2==null){
synchronized (Singleton.class){
if(INSTANCE2==null){
INSTANCE2=new Singleton();
}
}
}
return INSTANCE2;
}
}
2.2静态内部类
//私有静态内部类
public class Singleton {
private Singleton(){};
public static Singleton getInstance3(){return LazyHolder.INSTANCE;}
//私有静态内部类
private static class LazyHolder{
private static final Singleton INSTANCE=new Singleton();
}
}
测试用例:
//测试方式
for (int i=0;i<100;i++){
new Thread(()->{
System.out.println(Singleton.getInstance2().hashCode());
}).start();
}
测试结果:100 个都是1120223167
3.枚举
优点:内存中只存在一个对象实例,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
缺点:当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰
public enum SingletonEnum {
INCTANCE;
public void method(){
System.out.println("枚举类中定义方法!");
}
}
测试用例:
public static void main(String [] args){
//测试方式
for (int i=0;i<100;i++){
new Thread(()->{
System.out.println(SingletonEnum.INCTANCE.hashCode());
}).start();
}
}
测试结果:100 个都是1484015707
三、JAVA知识点
3.1synchronized
参考:https://www.jb51.net/article/226912.htm
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
【修饰一个代码块】一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞
Synchronized作用于整个方法的写法
//直接作用在方法上
public synchronized void method1() {
System.out.println("method1!");
}
//封装代码块
public void method2() {
synchronized(this) {
System.out.println("method2!");
}
}
- 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
- 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
- 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
3.2volatile
参考:(https://www.cnblogs.com/fhblikesky/p/13692645.html)
volatile 是 Java 中的关键字,是一个变量修饰符,被用来修饰会被不同线程访问和修改的变量。
【可见性】可见性是指多个线程访问同一个变量时,其中一个线程修改了该变量的值,其它线程能够立即看到修改的值。
【无原子性】volatile 只保证单次读/写操作的原子性,对于多步操作,volatile 不能保证原子性。
3.2静态内部类
在一个类中创建另外一个类,叫做成员内部类。这个成员内部类可以静态的(利用static关键字修饰),也可以是非静态的。使用方式参考2.2静态内部类
标签:Singleton,01,java,private,static,单例,线程,设计模式,public From: https://www.cnblogs.com/q994321263/p/16930262.html