序列化
序列化:將對象按照流的方式存儲到文本文件中或者再網絡中傳輸 對象---->流數據 序列化流 (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);
}
}