序列化、加密与多线程

#默认序列化不是安全的

class Student implements Serializable{

	private static final long serialVersionUID = -6878188780054330073L;
	private String name;
	private int age;
	private int weight;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	//对象在序列化时调用(可用于加密)
	private void writeObject(ObjectOutputStream out) throws IOException{
		//类似加密
		age=age>>2;
		name=Base64.encodeBase64String(name.getBytes("utf-8"));
		//执行序列化
		out.defaultWriteObject();
	}
	//对象在反序列化时调用(可用于解密)
	private void readObject(ObjectInputStream in)
	throws Exception{
		in.defaultReadObject();
		age=age<<2;
		name=new String(Base64.decodeBase64(name.getBytes("utf-8")));
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
		
}
/**默认序列化是安全的吗?不安全,如何实现安全序列化?*/
public class SerializableDemo01 {
	public static void main(String[] args)throws Exception {
		 ObjectOutputStream out=
		 new ObjectOutputStream(
		 new FileOutputStream("f.txt"));
		 Student s1=new Student();
		 s1.setName("苍老师");
		 s1.setAge(16);
		 //对象序列化
		 out.writeObject(s1);
		 out.close();
		 
		 ObjectInputStream in=
			new ObjectInputStream(
		 new FileInputStream("f.txt"));
		 Object obj=in.readObject();
		 System.out.println(obj);
		 in.close();
	}

}

#Base64与MD5
##Base64(可逆)

//commons.apache.org 官网下载codec
import org.apache.commons.codec.binary.Base64;
public class Base64Demo01 {
	public static void main(String[] args) {
		String s1="helloworld";
		//加密
		byte[] buf=Base64.encodeBase64(s1.getBytes());
		String s2=new String(buf);
		System.out.println(s2);
		//解密
		buf=Base64.decodeBase64(buf);
		String s3=new String(buf);
		System.out.println(s3);
	}
}

##MD5(不可逆)

public class MD5Demo01 {

	public static void main(String[] args)
	throws Exception{//MD5,SHA
		String password="123456";
		//e10adc3949ba59abbe56e057f20f883e
		//e10adc3949ba59abbe56e057f20f883e
		//e10adc3949ba59abbe56e057f20f883e
		MessageDigest mDigest=
		MessageDigest.getInstance("MD5");
		byte[] buf=mDigest.digest(password.getBytes());
		//System.out.println(buf.length);//16*8=128位
		//System.out.println(Arrays.toString(buf));
		StringBuilder sb=new StringBuilder();
		for(byte b:buf){
			String sHex=Integer.toHexString(b&0xff);
			if(sHex.length()==1){
				sHex="0"+sHex;
			}
			//System.out.println(sHex);
			sb.append(sHex);
		}
		System.out.println(sb.toString());//32bit
	}
}

public class MD5Demo02 {

	public static void main(String[] args)
	throws Exception{//MD5,SHA
		//77abeecc1d175ba4df89235f64ebbae0
		String password="123456";
		String email="qilei@tedu.cn";//salt(盐值)
		String content=password+email;
		MessageDigest mDigest=
		MessageDigest.getInstance("MD5");
		byte[] buf=mDigest.digest(content.getBytes());
		//System.out.println(buf.length);//16*8=128位
		//System.out.println(Arrays.toString(buf));
		StringBuilder sb=new StringBuilder();
		for(byte b:buf){
			String sHex=Integer.toHexString(b&0xff);
			if(sHex.length()==1){
				sHex="0"+sHex;
			}
			//System.out.println(sHex);
			sb.append(sHex);
		}
		System.out.println(sb.toString());//32bit
		
		String randomStr=
				UUID.randomUUID().toString();
		System.out.println(randomStr);
		
	}
}

//此API在eclipse中可能不能直接使用
//假如要使用可以在项目的buildpath中添加访问规则
import sun.misc.BASE64Encoder;
public class MD5Demo03 {
	public static void main(String[] args)
	throws Exception{
		String password="123456";
		//获得摘要对象
		MessageDigest mDigest=
		MessageDigest.getInstance("MD5");
		//获得字符串的摘要信息
		byte[] result=
		mDigest.digest(password.getBytes("utf-8"));
		//对摘要信息再次进行编码进制转换
		BASE64Encoder encoder=new BASE64Encoder();
		String s=encoder.encode(result);
		System.out.println(s);//4QrcOUm6Wau+VuBX8g+IPg==
	}
}
public class MD5Demo04 {

	public static void main(String[] args) {
		String s1="123456";
		String s2=DigestUtils.md5Hex(s1);
		System.out.println(s2);
		String s3=DigestUtils.sha1Hex(s2);
		System.out.println(s3);
		String s4=DigestUtils.md5Hex(s2);
		System.out.println(s4);
	}
}

#多线程
##锁同步与wait、notify协作

/**
 * 线程同步:多线程并发执行时在共享数据集的互斥与协作
 * 1)互斥:多线程在共享数据集上排队执行
 * a)同步代码块synchronized(同步锁){}
 * b)同步方法
 * b.1) public synchronized void method1(){}
 * b.2) public synchronized static void method2(){}
 * c)ReentrantLock (JDK1.5)
 * 2)协作:多线程在共享数据集上的通讯
 * a)构建于互斥基础之上
 * b)在同步代码块或同步方法中借助wait,notify,notifyall方法执行通讯
 * wait:表示等待,调用此方法的线程会阻塞,同时释放锁
 * notify/notifyall:表示唤醒或通知正在处于wait状态且具备相同锁对象
 * 的线程.
 * 用法:
 * 1)wait,notify,notifyall必须用在同步代码块或同步方法中
 * 2)wait,notify,notifyall必须由对象锁调用
 */
public class CommunicationDemo01 {
	static  String content;
	public  static void main(String[] args) {
		Thread t=new Thread(){
			@Override
			public void run() {
				content="helloworld";
				//通知具备相同锁并处于阻塞状态的对象
				synchronized (Object.class) {
					Object.class.notifyAll();
				}
			}
		};
		t.start();
		
		synchronized (Object.class) {
			while(content==null){
				try{Object.class.wait();}
				catch(Exception e){}
			}
		}
	
		System.out.println(content.toUpperCase());
	}
}

class Rect{}
class MyClass{}
class WorkThread03 extends Thread{
	private static Rect instance;
	@Override
	public void run() {
		//try{Thread.sleep(5000);}catch(Exception e){}
		instance=new Rect();
		synchronized (WorkThread03.class) {
			WorkThread03.class.notify();
		}
	}
	//静态方法默认使用的对象锁为方法所在类的类对象WorkThread03.class
	public synchronized static Rect getRect(){
		while(instance==null){
			try{WorkThread03.class.wait();}
			catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);}
		}
		return instance;
	}//SCJP,OCJP
}

public class CommunicationDemo03 {
    public static void main(String[] args) {
    	WorkThread03 w=new WorkThread03();
    	w.start();
    	System.out.println(w.getRect());
	}
}

##ThreadLocal

class DateFormatUtil{
private static  volatile ThreadLocal<SimpleDateFormat> td
=new ThreadLocal<SimpleDateFormat>();
// private static SimpleDateFormat sdf=new SimpleDateFormat(pattern)
public static SimpleDateFormat getDateFormat(){
	//1.从当前线程获取对象
	SimpleDateFormat sdf=td.get();
	//2.当前线程没有,则创建,然后绑定到当前线程
	if(sdf==null){
		//map.put(key,value)
		sdf=new SimpleDateFormat("yyyy-MM-dd");
		td.set(sdf);//绑定
	}
	//3.直接返回SimpleDateFormat对象
	return sdf;
}
public static void remove(){
	td.remove();
}
}
public class ThreadLocalDemo01 {
    public static void main(String[] args) {
	   SimpleDateFormat sdf1=DateFormatUtil.getDateFormat();
	   SimpleDateFormat sdf2=DateFormatUtil.getDateFormat();
	   System.out.println("sdf1="+sdf1);
	   System.out.println("sdf2="+sdf2);
	   //DateFormatUtil.remove();
	   new Thread(){
		   public void run() {
			   SimpleDateFormat sdf3=
			   DateFormatUtil.getDateFormat();
			   SimpleDateFormat sdf4=
			   DateFormatUtil.getDateFormat();
			   System.out.println("sdf3="+sdf3);
			   System.out.println("sdf4="+sdf4);
			   System.out.println(sdf4==sdf3);
			   System.out.println(sdf1==sdf3);
			   System.out.println(sdf1==sdf2);
		   };
	   }.start();
	   while(true){}
    }
}
/**HashSet
1)hashCode 不同直接存储
2)hashCode 相同,equals 也相同则认为是同一个对象,此对象不存储
3)hashCode 相同,再调用equals方法,equals 比较不同则存储

ArrayList存储结构:底层存储是数组,线性结构.
HashMap存储结构:数组+链表+红黑树
ConcurrentHashMap(1.8之前分段加锁,1.8之后红黑树)
*/

##volatile

class WorkThread extends Thread{
	private volatile boolean isExit=false;
	//private static String LOCK="LOCK";
	@Override
	public void run() {
		while(true){
			//synchronized (LOCK) {
				if(isExit){
					 System.out.println("work thread exit");
					 break;
				}
			//}
			
		}
	}
	public void setExit(boolean isExit) {
		//synchronized (LOCK) {
			this.isExit = isExit;
		//}
	}
}
public class VolatileDemo01 {
	public static void main(String[] args)
	throws Exception{
		WorkThread w=new WorkThread();
		w.start();
		Thread.sleep(200);
		w.setExit(true);
	}
}

#单例模式

/**
 * 单例模式(保证类的实例在内存中只有一份)
 * 1)属于对象的创建型模式(与对象创建有关)
 * 2)单例模式应用场景?
 * 2.1)池对象(字符串池,整数池,线程池,....)
 * 2.2)工具类
 * 2.3)....................
 * 单例模式设计:
 * 1)构造函数私有化
 * 2)类的内部构建对象
 * 3)类的外部通过类中的静态方法访问对象
 * 
 * 单例对象类型
 * 1)懒汉单例(何时需要何时创建):大对象(占用内存多),稀少用
 * 2)饿汉单例(类加载时创建):小对象(占用资源比较少),频繁用
 * @author adminitartor
 */
class Singleton01{//线程不安全的懒汉单例
	private Singleton01(){}
	private static Singleton01 instance;
	public static Singleton01 getInstance(){
		if(instance==null){
			instance=new Singleton01();
		}
		return instance;
	}//这个方法可能会存在线程安全问题(方法内部操作为非原子操作)
}
class Singleton02{//线程安全的懒汉单例
	private Singleton02(){}
	private static Singleton02 instance;
	synchronized public static Singleton02 getInstance(){
		if(instance==null){
			instance=new Singleton02();
		}
		return instance;
	}//线程安全了,性能降低了(每次只能有一个线程进入此方法获取对象)
}//如何改善这个类的性能.

class Singleton03{//线程安全的懒汉单例实现性能方法的改进
	private Singleton03(){}
	//volatile 保证可见,但不保证原子性
	//在双重判定场景下也会经常使用volatile关键字
	private static volatile Singleton03 instance;
    public static Singleton03 getInstance(){
    	if(instance==null){
    	 synchronized (Singleton03.class) {
    		if(instance==null){
    			instance=new Singleton03();
    		}
		 }//有些线程就不会再进入这个代码块了
    	}
		return instance;
	}
    //public static void display(){}
}
class Singleton04{
	//不存在线程安全问题的饿汉式单例(类加载时就构建对象)
	private Singleton04(){}
	private static final Singleton04 instance=
			new Singleton04();
	public static Singleton04 getInstance() {
		return instance;
	}
	//int array[]=new int[256];//256*4
    //public static void display(){}//Singleton04.display()
    //public void show(){}//Singleton04.getInstance().show();
};
class Singleton05{//改进版的饿汉单例(懒加载延迟对象创建)
	private Singleton05(){}
	static class Inner{//Inner类加载时创建对象
		static Singleton05 instance=new Singleton05();
	}
	public static Singleton05 getInstance() {
		return Inner.instance;
	}
	//int array[]=new int[256];
	//public static void display(){}Singleton05.display()
	
}
//枚举
enum Singleton06{//未改良版的饿汉单例
	A; //此对象类加载时就会创建
	public static void display(){}
	public void show(){}//Singleton06.A.show();
}//不适合大对象

//线程内部单例如何实现?(借助ThreadLocal)
public class SingletonDemo01 {

	public static void main(String[] args) {
		for(int i=0;i<5;i++){
			new Thread(){
				public void run() {
					System.out.println(
							Singleton02.getInstance());
				};
			}.start();
		}
		
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值