首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 學習雜談(四)—— 序列化機制與多線程編程核心難點

     編輯:Java 相關知識

序列化與反序列化

ObjectOutputStream (oos) / ObjectInputStream (ois) 實現對象 ↔ 二進制流轉換,支持文件、Socket 通道。

流初始化順序鐵律

輸出流必須先於輸入流初始化,否則拋異常。原因:ObjectInputStream 構造器調用 readStreamHeader() 讀取雙 Short 值決定緩存大小,依賴對端 ObjectOutputStream 已寫入 Header。

// 文件通道
File file = new File("C:/data.dat");
oos = new ObjectOutputStream(new FileOutputStream(file));
ois = new ObjectInputStream(new FileInputStream(file));

// Socket 通道
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
// 注意:此處 oos/ois 對接的是 socket 另一端的流,需保證對端輸出流先打開。

EOFException 非錯誤,而是正常終止信號

  • readObject() 循環讀取,數據盡頭拋 EOFException 表示連接關閉/發送結束。
  • 許多開發者誤以為是 Bug,實則是業務邏輯未處理「無數據」情況(如空指針、類轉換、數組越界導致發送端提前退出)。
  • 排查建議:單步調試發送端,定位真實異常拋出點,而非纠結接收端循環。

多線程編程四大核心難題

1. 線程 vs 對象

start() 啟動線程後,線程與 Runnable 對象無關。對象僅是內存資源+代碼段。主線程 + GC 線程至少兩個線程共存。

2. wait() / notify() 機制

  • wait():釋放當前對象所有鎖,進入等待集。sleep() 不釋放鎖。
  • 只能在 synchronized 代碼塊中調用(持有鎖)。
  • notify() 隨機喚醒一個等待線程;notifyAll() 喚醒所有,由優先級競爭唯一鎖。

3. suspend() 棄用原因

外部強制掛起線程破壞封裝,易導致死鎖/數據不一致。面向對象要求對象自主控制生命周期。

4. synchronized 重入鎖

class Parent { synchronized void f() {} }
class Child extends Parent {
    synchronized void f() { super.f(); } // 同一線程同一對象重入
}
  • 子類 f() 加鎖 → 進入調用 super.f() 再次嘗試加鎖。
  • JVM 檢測到當前線程已持有該對象鎖 → 重入成功,不阻塞。實際上第二把鎖未真正加上。
  • 本質:synchronized 阻止其他線程在同一對象上加鎖,不阻止持有鎖的線程重入。

總結

序列化注意流初始化順序與 EOF 含義;多線程核心在理解「鎖屬於對象、線程爭搶鎖、重入機制、wait/notify 配合同步」。實踐中多用 java.util.concurrent 高級組件,少寫底層同步代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved