单例模式用来创建的对象可以确保系统中只产生一个示例。主要有以下两种好处:1.对于频繁使用的对象可以省略创建对象所花费的时间 2.由于new操作的次数减少,对系统内存的使用频率也会降低。将减轻GC压力。缩短GC停顿时间。
public class SingleClassDemo {
//第一种方式 直接创建对象 需要时直接返回 public static SingleClassDemo sSingleClassDemo = new SingleClassDemo();
private SingleClassDemo() { System.out.println("创建单例对象"); }
public static SingleClassDemo getInstance() { return sSingleClassDemo; }
// 该类中的其他静态方法 //public static String otherMethod() { // return "otherMethod otherMethod!"; //}
}
/*** 测试类*/public class TestSingleClassDemo { @Test public void testInstance() {
SingleClassDemo instance = SingleClassDemo.getInstance(); System.out.println(instance); //打印结果:创建单例对象 top.wintp.demo.SingleClassDemo@50486d1d }}
如上述代码就是单例模式的一种简单的实现方式。试想我们这种实现方式会有什么问题呢?当该类中存在其他的静态方法的时候,我们直接调用该类的其他静态方法,也会创建该类的对象,这是我们不想得到的结果
调用示例:
public class TestSingleClassDemo { @Test public void testInstance() { //当调用该类的其他方法的时候,会初始化该类该类的静态变量 创建对象 String string = SingleClassDemo.otherMethod(); System.out.println(string); //打印结果:创建单例对象 cotherMethod otherMethod! }}
修改创建单例对象的时机,当有需要的时候再去创建对象。
public class LazSingleClassDemo {
private static LazSingleClassDemo mLazSingleClassDemo = null;
private LazSingleClassDemo() { System.out.println("创建懒加载模式的对象"); }
public static LazSingleClassDemo getmLazSingleClassDemo() {
if (mLazSingleClassDemo == null) { mLazSingleClassDemo = new LazSingleClassDemo(); }
return mLazSingleClassDemo; }
public static String otherMehod() {
return "otherMehod otherMehod"; }}
public class TestSingleClassDemo { @Test public void testInstance() {
// 懒加载模式 //在懒加载模式中 调用该类的其他方法并不会创建该类的对象 String string = LazSingleClassDemo.otherMehod(); System.out.println(string); //打印结果:otherMehod otherMehod }}
当多线程并发时,懒加载模式就可能会出现,当前线程检测为null,第二个线程检测为null,同时创建两个对象的情况。那就违背了单例的原则。
调用示例:
public class TestSingleClassDemo { @Test public void testInstance() { // 懒加载模式的线程并发问题 new Thread("t1") { public void run() { LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(lazSingleClassDemo); } }.start(); new Thread("t2") { public void run() { LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(lazSingleClassDemo); } }.start(); new Thread("t3") { public void run() { LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(lazSingleClassDemo); } }.start(); new Thread("t4") { public void run() { LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(lazSingleClassDemo); } }.start();
new Thread("t5") { public void run() { LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(lazSingleClassDemo); } }.start();
/* 打印结果如下:
创建懒加载模式的对象 创建懒加载模式的对象 t2 top.wintp.demo.LazSingleClassDemo@475f260c t1 top.wintp.demo.LazSingleClassDemo@55b9171e t3 top.wintp.demo.LazSingleClassDemo@475f260c t4 top.wintp.demo.LazSingleClassDemo@475f260c t5 top.wintp.demo.LazSingleClassDemo@475f260c */ }}
使用同步方法避免多线程并发。
public class LazSingleSyncClassDemo {
private static LazSingleSyncClassDemo mLazSingleClassDemo = null;
private LazSingleSyncClassDemo() { System.out.println("创建懒加载模式同步方法的对象"); }
//使用synchronized 关键字 public static synchronized LazSingleSyncClassDemo getmLazSingleClassDemo() {
if (mLazSingleClassDemo == null) { mLazSingleClassDemo = new LazSingleSyncClassDemo(); }
return mLazSingleClassDemo; }
public static String otherMethod() {
return "otherMethod otherMethod"; }}
如上代码,再次进行多线程进行调用就不会出现创建多个对象的结果 线程安全避免不了的就是性能会降低。下面就是线程同步与线程不同的测试程序执行时长
public class TestSingleClassDemo { @Test public void testInstance() { long beginTime = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { LazSingleClassDemo lazSingleClassDemo = LazSingleClassDemo.getmLazSingleClassDemo(); } long endTime = System.currentTimeMillis();
System.out.println(endTime - beginTime); //懒加载模式 不同步方法 用时间:2
beginTime = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { LazSingleSyncClassDemo lazSingleClassDemo = LazSingleSyncClassDemo.getmLazSingleClassDemo(); } endTime = System.currentTimeMillis();
System.out.println(endTime - beginTime); //懒加载模式 同步方法 用时间:5
}}
public class EndSingleClassDemo {
private static EndSingleClassDemo mLazSingleClassDemo = null;
private EndSingleClassDemo() { System.out.println("创建懒加载模式的对象"); }
/** * 静态内部类 */ private static class EndSingleClassDemoHolder { private static EndSingleClassDemo mLazSingleClassDemo = new EndSingleClassDemo(); }
public static EndSingleClassDemo getmLazSingleClassDemo() {
return EndSingleClassDemoHolder.mLazSingleClassDemo; }
public static String otherMehod() {
return "otherMehod otherMehod"; }}
public class TestSingleClassDemo { @Test public void testInstance() { new Thread("t1") { public void run() { EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(endSingleClassDemo); } }.start(); new Thread("t2") { public void run() { EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(endSingleClassDemo); } }.start(); new Thread("t3") { public void run() { EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(endSingleClassDemo); } }.start(); new Thread("t4") { public void run() { EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(endSingleClassDemo); } }.start(); new Thread("t5") { public void run() { EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo(); System.out.println(this.getName()); System.out.println(endSingleClassDemo); } }.start();
long beginTime = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { EndSingleClassDemo endSingleClassDemo = EndSingleClassDemo.getmLazSingleClassDemo(); } long endTime = System.currentTimeMillis();
System.out.println("用时间:" + (endTime - beginTime));
/* 打印结果如下:
创建懒加载模式的对象 t1 t2 t3 top.wintp.demo.EndSingleClassDemo@4dbb3e34 top.wintp.demo.EndSingleClassDemo@4dbb3e34 top.wintp.demo.EndSingleClassDemo@4dbb3e34 t4 top.wintp.demo.EndSingleClassDemo@4dbb3e34 t5 top.wintp.demo.EndSingleClassDemo@4dbb3e34 用时间:1 */
}}
一个优秀的程序员,不仅要会编写程序,更要学会编写高质量的程序。事虽难,做则成;路虽远,行则至。所涉及的代码:https://github.com/upuptop/WeChatQuXueChengXu