概念
单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。
动机
现实生活中,一个班级只能有一个班主任,一个公司只能有一个CEO。程序设计中,系统的任务管理器、序号生成器等都只需要一个,这些都可以用单例模式来实现。
实现
1.饿汉式
代码实现
public class MySingleTon1 {
private MySingleTon1(){} //私有化构造器
private static MySingleTon1 s=new MySingleTon1(); //私有静态实例
public static MySingleTon1 getIntance(){
return s;
} //公共get方法
}
优点
- 线程安全
- 无锁,效率高
缺点
- 造成内存浪费
2.懒汉式(线程不安全)
代码实现
public class MySingleTon2 {
private MySingleTon2(){}
private static MySingleTon2 s=null;
public static MySingleTon2 getInstance() throws InterruptedException {
if (s == null) {
Thread.sleep(1000); //加入线程休眠,测试时出现问题
s=new MySingleTon2();
}
return s;
}
}
测试用例
public class MyThread extends Thread{
@Override
public void run() {
MySingleTon2 s = null;
try {
s = MySingleTon2.getInstance();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(s);
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
优点
- 第一次调用才初始化,避免内存浪费。
缺点
- 线程不安全
- 加锁才可保证单例,效率低
3.懒汉式(线程安全)
代码实现
public class MySingleTon3 {
private MySingleTon3(){}
private static MySingleTon3 s=null;
private static Object obj=new Object();
public static MySingleTon3 getInstance() throws InterruptedException {
synchronized (obj){
if (s==null){
s=new MySingleTon3();
}
}
return s;
}
}
note:锁要加在if判断外,否则多线程时仍有可能会进入if条件内。
优点:
- 线程安全
缺点:
- 每次getInstance()都需要进入同步锁,效率低
4.懒汉式(双重判断)
代码实现
public class MySingleTon4 {
private MySingleTon4(){}
private static MySingleTon4 s=null;
private static Object obj=new Object();
public static MySingleTon4 getInstance() throws InterruptedException {
if (s == null) {
synchronized (obj){
if (s==null){
s=new MySingleTon4();
}
}
}
return s;
}
}
优点:
- 线程安全
- 无需多次进入同步锁,效率优化
5.静态内部类式
代码实现
public class MySingleTon5 {
private MySingleTon5(){}
private static class inner{
private static MySingleTon5 instance= new MySingleTon5();
}
public static MySingleTon5 getInstance(){
return inner.instance;
}
}
优点:
- 线程安全
- 效率高
- 不浪费内存