懒汉式单例
被外部類調用時才創建實例
//懶漢式單例 //在外部需要使用的時候才進行實例化 public class LazySimpleSingleton {private LazySimpleSingleton(){}//靜態塊,公共內存區域private static LazySimpleSingleton lazy = null;public synchronized static LazySimpleSingleton getInstance(){if(lazy == null){lazy = new LazySimpleSingleton();}return lazy;} } public class ExectorThread implements Runnable{@Overridepublic void run() {LazySimpleSingleton singleton = LazySimpleSingleton.getInstance(); // ThreadLocalSingleton singleton = ThreadLocalSingleton.getInstance();System.out.println(Thread.currentThread().getName() + ":" + singleton);} } public class LazySimpleSingletonTest {public static void main(String[] args) {Thread t1 = new Thread(new ExectorThread());Thread t2 = new Thread(new ExectorThread());t1.start();t2.start();System.out.println("End");} } public class LazyDoubleCheckSingleton {private volatile static LazyDoubleCheckSingleton lazy = null;private LazyDoubleCheckSingleton(){}public static LazyDoubleCheckSingleton getInstance(){if(lazy == null){synchronized (LazyDoubleCheckSingleton.class){if(lazy == null){lazy = new LazyDoubleCheckSingleton();//1.分配內存給這個對象//2.初始化對象//3.設置lazy指向剛分配的內存地址//4.初次訪問對象}}}return lazy;} } //這種形式兼顧餓漢式的內存浪費,也兼顧synchronized性能問題 //完美地屏蔽了這兩個缺點 //史上最牛B的單例模式的實現方式 public class LazyInnerClassSingleton {//默認使用LazyInnerClassGeneral的時候,會先初始化內部類//如果沒使用的話,內部類是不加載的private LazyInnerClassSingleton(){if(LazyHolder.LAZY != null){throw new RuntimeException("不允許創建多個實例");}}//每一個關鍵字都不是多余的//static 是為了使單例的空間共享//保證這個方法不會被重寫,重載public static final LazyInnerClassSingleton getInstance(){//在返回結果以前,一定會先加載內部類return LazyHolder.LAZY;}//默認不加載private static class LazyHolder{private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();} } public class LazyInnerClassSingletonTest {public static void main(String[] args) {try{//很無聊的情況下,進行破壞Class<?> clazz = LazyInnerClassSingleton.class;//通過反射拿到私有的構造方法Constructor c = clazz.getDeclaredConstructor(null);//強制訪問,強吻,不愿意也要吻c.setAccessible(true);//暴力初始化Object o1 = c.newInstance();//調用了兩次構造方法,相當于new了兩次//犯了原則性問題,Object o2 = c.newInstance();System.out.println(o1 == o2); // Object o2 = c.newInstance();}catch (Exception e){e.printStackTrace();}} } public class SeriableSingletonTest {public static void main(String[] args) {SeriableSingleton s1 = null;SeriableSingleton s2 = SeriableSingleton.getInstance();FileOutputStream fos = null;try {fos = new FileOutputStream("SeriableSingleton.obj");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(s2);oos.flush();oos.close();FileInputStream fis = new FileInputStream("SeriableSingleton.obj");ObjectInputStream ois = new ObjectInputStream(fis);s1 = (SeriableSingleton)ois.readObject();ois.close();System.out.println(s1);System.out.println(s2);System.out.println(s1 == s2);} catch (Exception e) {e.printStackTrace();}} } //反序列化時導致單例破壞 public class SeriableSingleton implements Serializable {//序列化就是說把內存中的狀態通過轉換成字節碼的形式//從而轉換一個IO流,寫入到其他地方(可以是磁盤、網絡IO)//內存中狀態給永久保存下來了//反序列化//講已經持久化的字節碼內容,轉換為IO流//通過IO流的讀取,進而將讀取的內容轉換為Java對象//在轉換過程中會重新創建對象newpublic final static SeriableSingleton INSTANCE = new SeriableSingleton();private SeriableSingleton(){}public static SeriableSingleton getInstance(){return INSTANCE;}private Object readResolve(){return INSTANCE;}} public final Object readObject()throws IOException, ClassNotFoundException {if (enableOverride) {return readObjectOverride();}// if nested read, passHandle contains handle of enclosing objectint outerHandle = passHandle;try {Object obj = readObject0(false);handles.markDependency(outerHandle, passHandle);ClassNotFoundException ex = handles.lookupException(passHandle);if (ex != null) {throw ex;}if (depth == 0) {vlist.doCallbacks();}return obj;} finally {passHandle = outerHandle;if (closed && depth == 0) {clear();}} } private Object readObject0(boolean unshared) throws IOException {boolean oldMode = bin.getBlockDataMode();if (oldMode) {int remain = bin.currentBlockRemaining();if (remain > 0) {throw new OptionalDataException(remain);} else if (defaultDataEnd) {/** Fix for 4360508: stream is currently at the end of a field* value block written via default serialization; since there* is no terminating TC_ENDBLOCKDATA tag, simulate* end-of-custom-data behavior explicitly.*/throw new OptionalDataException(true);}bin.setBlockDataMode(false);}byte tc;while ((tc = bin.peekByte()) == TC_RESET) {bin.readByte();handleReset();}depth++;totalObjectRefs++;try {switch (tc) {case TC_NULL:return readNull();case TC_REFERENCE:return readHandle(unshared);case TC_CLASS:return readClass(unshared);case TC_CLASSDESC:case TC_PROXYCLASSDESC:return readClassDesc(unshared);case TC_STRING:case TC_LONGSTRING:return checkResolve(readString(unshared));case TC_ARRAY:return checkResolve(readArray(unshared));case TC_ENUM:return checkResolve(readEnum(unshared));case TC_OBJECT:return checkResolve(readOrdinaryObject(unshared));case TC_EXCEPTION:IOException ex = readFatalException();throw new WriteAbortedException("writing aborted", ex);case TC_BLOCKDATA:case TC_BLOCKDATALONG:if (oldMode) {bin.setBlockDataMode(true);bin.peek(); // force header readthrow new OptionalDataException(bin.currentBlockRemaining());} else {throw new StreamCorruptedException("unexpected block data");}case TC_ENDBLOCKDATA:if (oldMode) {throw new OptionalDataException(true);} else {throw new StreamCorruptedException("unexpected end of block data");}default:throw new StreamCorruptedException(String.format("invalid type code: %02X", tc));}} finally {depth--;bin.setBlockDataMode(oldMode);}} private Object readOrdinaryObject(boolean unshared)throws IOException{if (bin.readByte() != TC_OBJECT) {throw new InternalError();}ObjectStreamClass desc = readClassDesc(false);desc.checkDeserialize();Class<?> cl = desc.forClass();if (cl == String.class || cl == Class.class|| cl == ObjectStreamClass.class) {throw new InvalidClassException("invalid class descriptor");}Object obj;try {obj = desc.isInstantiable() ? desc.newInstance() : null;} catch (Exception ex) {throw (IOException) new InvalidClassException(desc.forClass().getName(),"unable to create instance").initCause(ex);}passHandle = handles.assign(unshared ? unsharedMarker : obj);ClassNotFoundException resolveEx = desc.getResolveException();if (resolveEx != null) {handles.markException(passHandle, resolveEx);}if (desc.isExternalizable()) {readExternalData((Externalizable) obj, desc);} else {readSerialData(obj, desc);}handles.finish(passHandle);if (obj != null &&handles.lookupException(passHandle) == null &&desc.hasReadResolveMethod()){Object rep = desc.invokeReadResolve(obj);if (unshared && rep.getClass().isArray()) {rep = cloneArray(rep);}if (rep != obj) {// Filter the replacement objectif (rep != null) {if (rep.getClass().isArray()) {filterCheck(rep.getClass(), Array.getLength(rep));} else {filterCheck(rep.getClass(), -1);}}handles.setObject(passHandle, obj = rep);}}return obj;} obj = desc.isInstantiable() ? desc.newInstance() : null; boolean isInstantiable() {requireInitialized();return (cons != null); } if (obj != null &&handles.lookupException(passHandle) == null &&desc.hasReadResolveMethod()) {Object rep = desc.invokeReadResolve(obj);if (unshared && rep.getClass().isArray()) {rep = cloneArray(rep);}if (rep != obj) {// Filter the replacement objectif (rep != null) {if (rep.getClass().isArray()) {filterCheck(rep.getClass(), Array.getLength(rep));} else {filterCheck(rep.getClass(), -1);}}handles.setObject(passHandle, obj = rep);} } readResolveMethod = getInheritableMethod(cl, "readResolve", null, Object.class);?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結