前言:
本文将介绍多线程的实操案例——单例模式,单例模式是一种设计模式,其实操案例也细分为两种模式:懒汉模式和饿汉模式,其中也涉及静态工厂方法的使用。所以本文现简单介绍一下静态工厂方法,在进行介绍两个单例模式
一、静态工厂方法
所谓静态工厂方法就是将创建对象封装起来,然后在方法内部将创建的对象引用返回给外界调用。可能你会问这样做又有好处?往下看,将会得到答案。
我们一般来说创建对象都是通过使用对象构造器,也就是new一个对象。构造器可以有很多不同参数个数的同位体,并且这些构造器需要重载才能被创建出来,并且构造器名字都一样只能靠参数来进行区分,所以使用这个类的程序猿需要对这个类有一定了解才行。相同个数参数的构造器却是不能存在的,只能活一个。
而对于实际开发中,我们可能会需要使用相同参数个数,但是是不同参数意义(类型相同)的构造器,但是显而易见这个构造器压根不可能存在,所以这个时候就需要用到我们的静态工厂方法,如下代码:
class Person{
int age;
int weight;
private static Person person = null;
private Person(){
}
//构造有年龄属性的对象
public static Person AgeOfPerson(int age){
person = new Person();
person.age = age;
return person;
}
//构造有体重属性的对象
public static Person WeightOfPerson(int weight){
person = new Person();
person.weight = weight;
return person;
}
}
上面代码就可以根据不同的工厂方法构造出想要的对象。
【首先】工厂方法的命名都与参数有关的,这就是说明,我们能更清楚的知道这个方法的作用。相比之下,我们不需要对这个类有太多理解也能创建类对象。
【其次】要自定义工厂方法,还需要将类构造器设置为private,防止直接创建
【最后】工厂方法一般为类方法(静态方法),具有返回对象(返回对象的引用)
二、单例模式
在对工厂方法有一定了解后,我们开始介绍单例模式
1.什么是单例模式
单例模式是一种设计模式,单例模式能保证某个类在程序中只存在唯一一份实例, 而不会创建出多个实例,相当于处于一个被共享的位置。.
2.多线程中的单例模式
多线程中的单例模式有两种,一种是饿汉模式,一种是懒汉模式
为了方便理解饿汉模式和懒汉模式,我们举一个例子:
吃饭需要用到碗筷,对于饿汉来说,他必须把碗筷在每次结束战斗后都洗一次碗,来保证饿的时候有碗吃饭,相当于提前行动。而懒汉呢?他比较懒,什么时候吃饭就什么时候洗,不吃就不洗,相当于按需行动,所以基于此,我们可以利用这“饿汉”和“懒汉”的特性构造出不同的两种单例设计模式。
1)饿汉模式
直接上代码:
//饿汉模式
class Singleton{
//1.线程在初始直接创建实例
private static Singleton instance = new Singleton();
//2.设置私有无参构造器,防止被主动创建实例
private Singleton(){}
//3.创建一个方法将这个对象的引用返回(静态工厂方法)
public static Singleton getInstance(){
return instance;
}
}
代码中,是提前创建好了类对象,然后等工厂方法调用就将这个引用返回,所以可以看出,getInstance方法返回的引用一直都是同一个Singleton对象
2)懒汉模式
相比于饿汉模式,懒汉模式又分为单线程和多线程,多线程会稍微复杂一点,因为其涉及到锁的应用
懒汉模式——单线程
//懒汉模式--单线程
class Singleton1{
//1.设置类变量,但是被赋值为null值,因为懒汉模式只在需要的时候才进行创建实例
private static Singleton1 instance = null;
//2.设置私有无参构造器,防止被主动创建实例
private Singleton1(){}
//3.构建返回对象实例的引用
public static Singleton1 getInstance(){
//判断这个对象是否实例化了,如果有就直接返回,否则先创建在返回
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
懒汉模式——多线程
//懒汉模式--多线程
class Singleton2{
//1.设置类变量,但是被赋值为null值,因为懒汉模式只在需要的时候才进行创建实例,加上volatile防止编译'优化'
private static volatile Singleton2 instance = null;
//2.设置私有无参构造器,防止被主动创建实例
private Singleton2(){}
//3.构建返回对象的引用方法
public static Singleton2 getInstance(){
//4.与懒汉单线程模式不一样的是,多线程模式需要考虑多个线程同时访问的问题,这个时候需要对对象进行上锁保护
//5.这里上锁的设置对象用到是类对象,也就是这个类的class文件,因为这个类对象独有一份,可以被所以懒汉模式多线程都使用到,并且也符合单例模式的概念
//6.但是如果这样简单的设置锁,也是不行的,因为假如对象已经被实例了,就没有必要设置上锁浪费不必要的实际,所以还得多上层判断,达到降低竞争锁的频率
//synchronized(Singleton2.class){
// if(instance == null){
// instance = new Singleton2();
// }
//}
if(instance == null) {
//7.在这里多上一层判断,虽然有两个一样的 if(instance == null) 但是效果是不一样的.
//8.第一层就是用来判断有没有已经被实例化了,如果有就直接返回引用达到和饿汉模式一样效果,
//如果没有就是进入锁,等一个锁完成后才到另一个线程得到锁,开始判断,但是这个时候,对象已经被实例出来的,所以第二个instance的判断为false,然后就直接返回
synchronized (Singleton2.class) {
if (instance == null) {
instance = new Singleton2();
}
}
}
return instance;
}
}
代码的说明已经在块里面了,请耐心看完哦~
个人笔记使用~~