序列化
序列化:将对象按照流的方式存储到文本文件中或者再网络中传输 对象---->流数据 序列化流 (ObjectOutputStream)
反序列化:将文本文件中的流对象或者网络传输中的流对象还原成对象 流数据--->对象 反序列化流(ObjectInputStream)
java.io.NotSerializableException :当前类未实现序列化功能的异常
Serializable:接口 没有构造方法,没有字段,也没有方法
接口---->标记接口
自定义类要实现序列化功能,必须实现接口Serializable接口
类实现了serializable也意味着他是标记类
假设之前操作针对Peroson操作序列的时候,产生一个标记 Preson.class--->固定ID 100
name -100
age -100
已经序列化完毕了,然后有修改了Person类里面的一些东西,加入了toString()
Person.class---固定id -- 200
org.westos_01.Person; local class incompatible:
stream classdesc serialVersionUID = -428218385429329797,
local class serialVersionUID = -5865763454468005049
因为手动修改了这些类的属性/成员变量,将序列化版本Id改变了
InvalidClassException:一般情况:该类的序列版本号与从流中读取的类描述符的版本号不匹配
实际开发中,不想多次对当前这些序列化,如果这样做,非常麻烦?
如何解决呢?
让当前实现类序列化功能的这个类产生一个固定ID,注意看程序有黄色警告线,直接就点它固定Id
创建一个序列化流对象
public ObjectOutputStream(OutputStream out)
public final void writeObject(Object obj)
创建反序列化流对象
public ObjectInputStream(InputStream in)
public final Object readObject():从 ObjectInputStream 读取对象。
public static void main(String[] args) throws Exception { extracted(); extracted2(); } private static void extracted2() throws IOException, FileNotFoundException, Exception { ObjectInputStream ois=new ObjectInputStream(new FileInputStream("ois.txt")); Object object = ois.readObject(); ois.close(); System.out.println(object); } private static void extracted() throws IOException, FileNotFoundException { ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("ois.txt")); Student s=new Student("张三", 25); oos.writeObject(s); oos.close(); }
class Student implements Serializable{ private static final long serialVersionUID = 1L;
属性集合类
Properties:表示了一个持久的属性集(简称:属性集合类) extends Hashtable<K,V> Map集合的
可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
public Properties():无参构造
属性集合类的特有功能:
public Object setProperty(String key, String value) :给属性列表中添加键和值,并且强制都使用String
public Set<String> stringPropertyNames():遍历的功能
public String getProperty(String key)用指定的键在此属性列表中搜索属性
可保存在流中或从流中加载,只能使用属性集合类
public void store(Writer writer,String comments):把集合中的数据保存文本文件中(属性集合)
public void load(Reader reader):将文本文件中的数据加载到属性集合中
private static void extracted2() throws Exception { FileReader fr=new FileReader("name.txt"); Properties pro=new Properties(); pro.load(fr);; fr.close(); System.out.println(pro); }
多线程
JVM:Java虚拟机 识别main(主线程)
MyThread类就是一个执行线程类
并且重写Thread类中的run 方法
run()方法里面应该是一些耗时的操作,IO操作/循环语句..
class MyThread extends Thread{ @Override public void run() { System.out.println("helloworld"); for(int x = 0 ;x <200; x ++) { //两个线程都需要执行这个代码 System.out.println(x); } } }
如何实现多线程程序呢?
要实现多线程程序,需要开启进程,
开启进程,是需要创建系统资源,但是Java语言不能创建系统资源
只有C/C++可以创建系统资源, 利用c语言创建好的系统资源实现
Java提供了一个类:Thread类
实现多线程程序的步骤:
1)将类声明为 Thread 的子类
2)该子类应重写 Thread 类的 run 方法
3)在主线程进行该自定义的线程类的对象的创建
public class 多线程的创建 { public static void main(String[] args) { MyThread mt=new MyThread(); mt.start(); MyThread mt2=new MyThread(); mt2.start(); } }
并行和并发(高并发:MyBatis --->IBatis:半自动化)
强者逻辑上的同时,指的是同一个时间段内
后者物理上的同时,指的是同一个时间点
Thread 类提供了一些方法
public final void setName(String name):给线程起名称
public final String getName() :获取线程名称
Thread类中提供另一个功能:
public static Thread currentThread():返回当前正在执行的线程对象的引用
private static int threadInitNumber; 当前线程编号
public final void setDaemon(boolean on) :true时,表示为守护线程
将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。(守护线程不会立即结束掉,它会执行一段时间在结束掉)
该方法必须在启动线程前调用。
public static void main(String[] args) { //创建两个子线程 ThreadDaemon td1 = new ThreadDaemon() ; ThreadDaemon td2 = new ThreadDaemon() ; td1.setName("张飞"); td2.setName("关羽"); //在启动之前,设置为守护线程 td1.setDaemon(true); td2.setDaemon(true); td1.start(); td2.start(); Thread.currentThread().setName("刘备"); for(int x =0 ; x < 5 ; x ++) { System.out.println(Thread.currentThread().getName()+":"+x); } }
跟线程优先级相关的方法:
public final int getPriority()返回线程的优先级。
public final void setPriority(int newPriority)更改线程的优先级
线程存在一个默认优先级
public static final int MAX_PRIORITY 10 最大优先级
public static final int MIN_PRIORITY 1 最小优先级
public static final int NORM_PRIORITY 5 默认优先级
public final void join():等待该线程终止 interruputedException 中断异常
分别创建三个子线程,让第一个子线程执行之后,调用join()等待该线程中,在执行t2,t3线程
public static void sleep(long millis):线程睡眠 指定是时间毫秒值
throws InterruptedException
public void run() { for(int x = 0 ; x <100 ; x ++) { //t1,t2 //t1, 0,1 //t2来了 ,3,4,5,6,7,8 //t1 2 ,,, System.out.println(getName()+":"+x+",日期是:"+new Date()); //困了,想睡十秒钟 try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } }
两个区别?
public final void stop() ;强迫线程停止执行。 不会执行了 (过时了),方法能使用的
public void interrupt()中断线程。 表示中断线程的一种状态
public final void stop() ;强迫线程停止执行。 不会执行了 (过时了),方法能使用的
public static void yield()暂停当前正在执行的线程对象,并执行其他线程
public static void main(String[] args) { //创建ThreadStop类对象 ThreadStop st = new ThreadStop() ; st.start() ; //如果3秒不醒来,我就干掉你 try { st.sleep(3000); // st.stop(); st.interrupt();// 中断 } catch (InterruptedException e) { // e.printStackTrace(); System.out.println("程序出现了中断异常"); } }
实现多线程程序的第二种方式:
1)自定义一个类,实现Runnable接口
2)实现接口中的run方法,对耗时的代码进行操作
3)然后在主线程中创建该了对象,将该类对象做为一个资源类,创建Threadd类的对象,将刚才的资源类作为参数进行传递
public class MyThread implements Runnable { @Override public void run() { for(int x= 0; x <100 ; x ++) { // System.out.println(getName()+":"+x); System.out.println(Thread.currentThread().getName()+":"+x); } }