#默认序列化不是安全的
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();
}
}
}