Java中单例(Singleton)模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器和控制器常被设计成单例模式。
1,饿汉式---在类初始化时,已经自行实例化
public class Person{
private static final Person person=new Person();
//私有构造函数,外界无法使用
private Person(){
}
//提供一个方法,获得对象
public static Person getPerson(){
return person;
}
}
注:饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
缺点:饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,
2,懒汉式(线程不安全)--顾名思义,什么时候用,什么时候创建
public class Person{
private static Person person;
//私有构造函数
private Person(){
}
public static Person getPerson(){
if(person==null){
person=new Person();
}
return person;
}
3,懒汉式(线程安全)
public class Person{
private static Person person=null;
private Person(){
}
//添加 synchronized 同步锁
public static synchronized Person getPerson(){
if(person==null){
person=new Person();
}
return person;
}
}
注:在2.懒汉式基础上,添加同步锁,使得在多线程中可以使用。例如:当两个线程同时想创建实例,由于同一时刻只有一个线程能够得到同步锁,当第一个线程得到后第二个线程只能等待,如果没有创建该实例,就会创建。第一个线程释放同步锁以后第二个线程才能加上同步锁,执行内部代码,由于第一个线程已经创建了实例,所以第二个线程不需要重复创建。保证了多线程环境下也只有一个实例。
缺点:每次通过 getPerson() 方法得到实例的时候都会有一个试图去获取同步锁的过程,然而加锁是很耗时的,所以能避免就避免。
4,懒汉式(双重锁,线程安全)
public class Person{
private static Person person=null;
private Person(){
}
public static Person getPerson(){
if(person==null){
synchronized(Person.class){
if(person==null){
person=new Person();
}
}
}
return person;
}
}
注:只有在person==null的时候,才需要获取同步锁,创建一次实例。当实例被创建,则无需试图加同步锁,避免3中的问题。
缺点:使用双重if判断,复杂,容易出错。
5,静态内部类(建议使用)
public class Person{
private Person(){
}
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static class SingletonPerson{
private final static Person person=new Person();
}
public static Person getPerson(){
return SingletonPerson.person;
}
}
注:上面的SingletonPerson
内部类的实例与外部类的实例没有绑定关系,只有被调用才会被加载,也就是实现了延时加载。即按需创建实例。
网友评论