Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。
这样的模式有几个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
java实现要点:
1.单例类:构造方法私有、创建静态对象实例
2.static 修饰getInstance方法可取得唯一对象实例
一、单例类(饿汉式)
package Singleton;
public class Singleton {
//静态实例
private static Singleton singleton = new Singleton();
//私有构造方法
private Singleton (){
System.out.println("产生对象实例");
}
public static Singleton getInstance(){
return singleton;
}
}
二、饿汉式测试类
package Singleton;
public class TestSingleton {
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
//实例地址比较
if(singleton1 == singleton2){
System.out.println("是同一对象实例");
}
}
}
优点:这种方式的实现比较简单,在类加载的时候就完成了实例化,避免了线程的同步问题。
缺点:由于在类加载的时候就实例化了,所以没有达到Lazy Loading(懒加载)的效果,也就是说可能我没有用到这个实例,但是它也会加载,会造成内存的浪费(但是这个浪费可以忽略,所以这种方式也是推荐使用的)。
三、懒汉式双重校验锁【延迟加载和线程安全】
public class Singleton {
/**
* 懒汉式变种,属于懒汉式中较好的写法
*/
private static Singleton instance=null;
private Singleton() {System.out.println("创建了一个实例");};
public static Singleton getInstance(){
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
synchronized关键字作用于一个类Singleton时,是给这个Singleton类加锁,Singleton的所有对象用的是同一把锁
多线程测试类
package Singleton;
/**
* @author Leonardo
*/
public class TestSingleton {
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
//实例地址比较
if(singleton1 == singleton2){
System.out.println("是同一对象实例");
}
newRunnable();
}
private static void newRunnable(){
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i<3; i++){
System.out.println("thread t1 > " + i);
Singleton singleton = Singleton.getInstance();
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"t1").start();
new Thread(()-> {
for (int i = 0; i<3; i++){
System.out.println("thread t2 > " + i);
Singleton singleton = Singleton.getInstance();
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"t2").start();
}
}
测试结果
四、静态内部类
public class Singleton{
private Singleton() {};
private static class SingletonHolder{
private static Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}