单例适用场景:
1. 需要生成唯一序列的环境
2. 需要频繁实例化然后销毁的对象。
3. 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
4. 方便资源相互通信的环境
下面就了解一下静态内部类模式:
通过静态内部类实现单例的实现单号的生成,实际就是把类似把对象私有化(私有化构造器),让别人无法调用它的对象,只能通过调用 getInstance 静态方法返回该类对象。而getInstance静态方法判断如果有该对象存在就返回该对象,如果没有再创建一个新对象返回,所以就达到返回的对象是同一个的目的或者没有就创建一个新对象,后续的调用就是返回同一个对象;我在getInstance方法里面放了一个同步但它只是同步返回对象,防止同时生成两个新对象;如果不明白可以看下面是如何调用和证明该对象是唯一的;
在类里面创建两个线程,模仿两个人同时调用会不会出现问题:
这里输出静态的单号生成方法,并且输出调用的线程名称;
下面来看一下部分运行效果;
可以看到对象哈希是同一个;第一第二行都生成了哈希对象为什么呢?两线程调用对象比较快,导致第一个线程还没有执行run方法,第二个线程就去获取对象,然后就出现运行出两个对象哈希值;
代码:
public class PrimaryGenerater {
private static String number=null;
private static PrimaryGenerater primaryGenerater = null;
//私有化构造器
private PrimaryGenerater() {
}
/**
* 取得PrimaryGenerater的单例实现
*
* @return
*/
public static PrimaryGenerater getInstance() {
if (primaryGenerater == null) {
//synchronized同步锁
synchronized (PrimaryGenerater.class) {
if (primaryGenerater == null) {
primaryGenerater = new PrimaryGenerater();
}
}
}
System.out.println("对象哈希值: "+primaryGenerater.hashCode());
return primaryGenerater;//返回同一对象
}
/**
* 生成下一个编号
* @param str 生成的编号前缀
*/
public synchronized String generaterNextNumber(String str) {
String finalNumber = null;
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");//设置日期格式
if (!Tools.isNotNull(number)) {
number = "00000";// 第一次初始化编号
}
DecimalFormat df = new DecimalFormat("00000");//定义格式
finalNumber = str+dateFormat.format(date)+ df.format(1 + Integer.parseInt(number));
number=df.format(1 + Integer.parseInt(number));
return finalNumber;
}
public static void main(String[] args) {
MyThread1 thread1=new MyThread1();
MyThread1 thread2=new MyThread1();
thread1.start();
thread2.start();
}
}
class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("静态内部类:"+PrimaryGenerater.getInstance().generaterNextNumber("GD")+" "+Thread.currentThread().getName());
System.out.println("静态内部类:"+PrimaryGenerater.getInstance().generaterNextNumber("GD")+" "+Thread.currentThread().getName());
System.out.println("静态内部类:"+PrimaryGenerater.getInstance().generaterNextNumber("GD")+" "+Thread.currentThread().getName());
for (int j = 0; j < 3; j++) {
System.out.println("静态内部类:"+PrimaryGenerater.getInstance().generaterNextNumber("GD")+" "+Thread.currentThread().getName());
System.out.println("静态内部类:"+PrimaryGenerater.getInstance().generaterNextNumber("GD")+" "+Thread.currentThread().getName());
System.out.println("静态内部类:"+PrimaryGenerater.getInstance().generaterNextNumber("GD")+" "+Thread.currentThread().getName());
}
}
}
}
如有什么不当请多多指教;