本章的知识点非常重要,通过单例模式与多线程技术相结合,在这个过程中能发现很多从未考虑的情况,一些不良的程序设计方法如果应用在商业项目中,将会遇到非常大的麻烦。本章的案例也将充分说明,线程与某些技术相结合时要考虑的事情有很多。如何使单例模式遇到多线程是安全的、正确的。
立即加载/饿汉模式
什么是立即加载?立即加载就是使用类的时候已经将对象创建完毕,常见的实现方法就是直接new实例化。而立即加载从中文的语境来看,有着急、急迫的含义,所以也称饿汉模式。
立即加载/ 饿汉模式是在调用方法前,实例已经被创建了。
package com.pro;public class MyObject {
//立即加载方式==饿汉模式 private static MyObject myObject = new MyObject(); private MyObject(){
} public static MyObject getInstance(){
//此代码版本为立即加载 // 因为getInstall()方法没有同步,所以有可能出现非线程安全问题 return myObject; }}
public class MyThread extends Thread{
@Override public void run() {
System.out.println(MyObject.getInstance().hashCode()); }}
控制台打印的hashCode是同一个值,说明对象是同一个,也就实现了立即加载单例设计模式。
02
延迟加载/懒汉模式
什么是延迟加载?延迟加载就是调用get方法时实例才被创建,常见的实现方法就是get()方法中进行new实例化。~懒汉模式。
package com.pro;public class MyObject {
//立即加载方式==饿汉模式 private static MyObject myObject; private MyObject(){
} public static MyObject getInstance(){
if(myObject != null){
}else {
myObject = new MyObject(); } return myObject; }}
可以看到取得一个对象的实例,但是如果在多线程环境中,就会出现多个实例的情况,与单例模式的初衷相背离的。
03
延迟加载/懒汉模式的缺点
public class MyObject {
//立即加载方式==饿汉模式 private static MyObject myObject; private MyObject(){
} public static MyObject getInstance(){
try {
if (myObject != null) {
} else {
//模拟在创建对象之前做一些准备性工作 Thread.sleep(3000); myObject = new MyObject(); } }catch (InterruptedException e){
e.printStackTrace(); } return myObject; }}
控制台打印了3种hashCode,说明创建了3个对象,并不是单例的,这就是错误的单例模式。
04
延迟的加载/懒汉模式的解决方案
方法上加锁
public class MyObject {
//立即加载方式==饿汉模式 private static MyObject myObject; private MyObject(){
} //设置同步方法效率太低了,整个方法被上锁 synchronized public static MyObject getInstance(){
try {