设计模式
程序员在解决一个问题的时候,总结出来的一种解决方案,一种套路。
在可读性、可靠性、可扩展性、执行效率等等有优势,最佳的实践。
单例模式
①需求:项目中只允许一个实例对象。比如,线程池。
②方案:static
构造函数私有化,把对象的创建移动到类内部,通过public的方法对外提供。
③局限:单一职能原则
原例
会创建两个对象,结果为false
public class Singleon {
private Singleon(){
}
public static Singleon getInstance(){
Singleon s = new Singleon();
return s;
}
public static void main(String[] args) {
Singleon s1 = Singleon.getInstance();
Singleon s2 = Singleon.getInstance();
System.out.println(s1==s2);//false
}
}
①饿汉式
- 方式一:饿汉式
- 特点:①简单 ②支持多线程
- 缺点:类加载时就创建了对象,浪费内存。—不支持懒加载
public class Singleon1 {
private static Singleon1 s = new Singleon1();
private Singleon1(){
}
public static Singleon1 getInstance(){
return s;
}
public static void main(String[] args) {
Singleon1 s1 = Singleon1.getInstance();
Singleon1 s2 = Singleon1.getInstance();
System.out.println(s1==s2);//true
}
}
②懒汉式
- 方式二:懒汉式
- 特点:节省了内存
-
借助同步方法synchronized,保证多线程下的单例
- 缺点:效率降低
public class Singleon2 {
private static Singleon2 s ;
private Singleon2(){}
public synchronized static Singleon2 getInstance(){
if(s==null){
s = new Singleon2();
}
return s;
}
//synchronized 加同步方法,防止两个线程都进来加载,可以保证每次只会只有一个线程进来加载数据
public static void main(String[] args) {
Singleon2 s1 = Singleon2.getInstance();
Singleon2 s2 = Singleon2.getInstance();
System.out.println(s1==s2);//true
}
}
③双检式
- 方式三:双检式
- 特点:节省了内存
-
同步代码块的方式,来保证多线程下的单例
-
懒加载
-
节省内存
- 缺点:代码稍微复杂
public class Singleon3 {
private static Singleon3 s ;
private Singleon3(){}
public static Singleon3 getInstance(){
if(s==null){
//synchronized 加同步代码块,防止两个线程都进来加载,可以保证每次只会只有一个线程进来加载数据
synchronized (Singleon3.class){
if(s==null){
s = new Singleon3();
}
}
}
return s;
}
public static void main(String[] args) {
Singleon3 s1 = Singleon3.getInstance();
Singleon3 s2 = Singleon3.getInstance();
System.out.println(s1==s2);//true
}
}
④借助静态内部类来实现懒加载
- 方式四:
-
借助静态内部类来实现懒加载
-
支持多线程的
public class Singleon4 {
private Singleon4(){
}
public static Singleon4 getInstance(){
return new InnerClass().singleon4;
}
private static class InnerClass{
static Singleon4 singleon4= new Singleon4();
}
public static void main(String[] args) {
Singleon4 s1 = Singleon4.getInstance();
Singleon4 s2 = Singleon4.getInstance();
System.out.println(s1==s2);//true
}
}