单例模式:一个类只有一个实例,并提供一个全局访问点。
直接new一个静态的对象,把构造方法设置成私有的,不能在Printer类以外的地方创建实例。
public class Printer {
private static Printer printer = new Printer();
private Printer (){}
public static Printer getInstance(){
return printer;
}
}
这种方式在不使用这个对象的时候也会被创建,所以可以先判断该类是否有创建实例,创建过就直接return,永远保持只创建一个实例。这种方式只有在被使用的时候才会去初始化。
public class Printer {
private static Printer printer;
private Printer(){
}
public static Printer getInstance(){
if(printer == null){
printer = new Printer();
}
return printer;
}
}
public class test {
public static void main(String[] args) {
//用这种方式会提示错误
//Printer printer = new Printer();
Printer printer1 = Printer.getInstance();
Printer printer2 = Printer.getInstance();
//输出结果为:true
System.out.println(printer1 == printer2);
}
}
运行多线程时出现了问题,当第一个线程通过if判断但还没有创建实例时,第二个线程也进行了if判断,然后也通过了。最简单的办法是在创建对象的方法上加上synchronized关键字。
public class Printer {
private static Printer printer;
private Printer(){
}
public synchronized static Printer getInstance(){
if(printer == null){
printer = new Printer();
}
return printer;
}
}
每一次都去同步会比较损耗性能,其实我们只需要在第一次还没有创建对象的时候同步就可以了,之后的每一次同步都是多余的。所以我们在同步之前先判断是否创建了对象。(不要忘记了volatile 关键字,这种方式只有jdk1.5版本以上才能使用)
public class Printer {
private volatile static Printer printer;
private Printer(){
}
public static Printer getInstance(){
if(printer == null){
synchronized(Printer.class){
if(printer == null){
printer = new Printer();
}
}
}
return printer;
}
}
再补充一种静态内部类创建单例的方式。
public class InnerSingleton {
private InnerSingleton(){};
public static InnerSingleton getInstance(){
return InnerClass.instance;
}
static class InnerClass{
private static InnerSingleton instance = new InnerSingleton();
}
}
单件模式就介绍完了,完美!