单例模式(多线程不安全,序列化不安全,反射不安全实例)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/lv836735240/article/details/49925963
<pre name="code" class="html">import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;


public class SingletonTwo implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private int number;
	
	
	private  final static SingletonTwo s=new SingletonTwo();
	
	private SingletonTwo(){}
	
	private SingletonTwo(int number){
		this.number=number;
	}
	public  static SingletonTwo getInstace()
	{
		return s;
	}
	public void sayHello(){
		System.out.println("hello");
	}
	
	
	
	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}
	
	 /*private Object readSolve()
	 {
		 return s;
	 }*/ 此段代码保证反序列化的安全性
	 
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		SingletonTwo s=SingletonTwo.getInstace();//原始类
		s.sayHello();
		s.setNumber(10);
		ObjectOutputStream out;
		
		
		//反序列化不安全
		try {
			
			//序列化
			out = new ObjectOutputStream(new FileOutputStream("E://Singleton.txt"));
			out.writeObject(s);
			System.out.println("序列化成功");
			out.close();
			//反序列化
			 ObjectInputStream in = new ObjectInputStream(new FileInputStream("E://Singleton.txt"));
			 SingletonTwo dest=(SingletonTwo) in.readObject();
			 dest.setNumber(100);
			 System.out.println(dest.getNumber());
			 System.out.println("原始类 和 反序列话类相等吗  "+s.equals(dest));
			
		} catch (FileNotFoundException e1) {
			// TODO 自动生成的 catch 块
			e1.printStackTrace();
		} catch (IOException e1) {
			// TODO 自动生成的 catch 块
			e1.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	   
	    
	    
		MyThread m=new MyThread(s);//多线程不安全
		new Thread(m).start();
		MyThread m1=new MyThread(s);
		new Thread(m1).start();
		
		
		System.out.println("我是单例类"+s.getNumber());
		try {//私有的反射机制不安全
			Constructor<SingletonTwo>[] c=(Constructor<SingletonTwo>[]) Class.forName("com.create.destroy.object.singleton.SingletonTwo").getDeclaredConstructors();
			for(int i=0;i<c.length;i++)
			{
				Constructor<SingletonTwo> cs=c[i];
				Type []types=cs.getGenericParameterTypes();
				if(types!=null && types.length>0)
				{
					for(int j=0;j<types.length;j++)
					{
						System.out.println(types[j]);
					}
				}else
				{
					SingletonTwo st=cs.newInstance(null);
					 st.setNumber(1);
					 System.out.println("原始类 和 反射类相等吗  "+st.equals(s));
					
				}
			}
		} catch (SecurityException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	  
	
	}

}
class MyThread implements Runnable{
	private SingletonTwo s;
	/* (非 Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public MyThread(SingletonTwo s)
	{
		this.s=s;
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		SingletonTwo t=SingletonTwo.getInstace();
		System.out.println("********************************************************");
		System.out.println("1.多线程类和原始类相等吗?"+s.equals(t));
		System.out.println("如果再多线程中使用反序列化还会相等吗??? 使用反射机制呢??");
		System.out.println("*************************可能为false****************************** ");
	}
	
}

总结如下:通过反射机制,一定不安全。多线程可能造成不安全,序列化也可能造成不安全

 
 
 

猜你喜欢

转载自blog.csdn.net/lv836735240/article/details/49925963
今日推荐