自定義序列化
在這個例子中,我們想要建立一個將生成並輸出到控制檯的類,這是一個兩個整數範圍之間的隨機數,它在初始化期間作為引數傳遞。
public class SimpleRangeRandom implements Runnable {
private int min;
private int max;
private Thread thread;
public SimpleRangeRandom(int min, int max){
this.min = min;
this.max = max;
thread = new Thread(this);
thread.start();
}
@Override
private void WriteObject(ObjectOutputStreamout) throws IO Exception;
private void ReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
public void run() {
while(true) {
Random rand = new Random();
System.out.println("Thread: " + thread.getId() + " Random:" + rand.nextInt(max - min));
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
現在,如果我們想要使這個類 Serializable 存在一些問題。Thread 是某些不可序列化的系統級類之一。所以我們需要將執行緒宣告為瞬態。通過這樣做,我們將能夠序列化此類的物件,但我們仍然會遇到問題。正如你在建構函式中看到的,我們設定了隨機函式的最小值和最大值,然後我們啟動了負責生成和列印隨機值的執行緒。因此,當通過呼叫 readObject()
來恢復持久化物件時,建構函式將不會再次執行,因為沒有建立新物件。在這種情況下,我們需要通過在類中提供兩個方法來開發自定義序列化。那些方法是:
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
因此,通過在 readObject()
中新增我們的實現,我們可以啟動並啟動我們的執行緒:
class RangeRandom implements Serializable, Runnable {
private int min;
private int max;
private transient Thread thread;
//transient should be any field that either cannot be serialized e.g Thread or any field you do not want serialized
public RangeRandom(int min, int max){
this.min = min;
this.max = max;
thread = new Thread(this);
thread.start();
}
@Override
public void run() {
while(true) {
Random rand = new Random();
System.out.println("Thread: " + thread.getId() + " Random:" + rand.nextInt(max - min));
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
thread = new Thread(this);
thread.start();
}
}
以下是我們示例的主要內容:
public class Main {
public static void main(String[] args) {
System.out.println("Hello");
RangeRandom rangeRandom = new RangeRandom(1,10);
FileOutputStream fos = null;
ObjectOutputStream out = null;
try
{
fos = new FileOutputStream("test");
out = new ObjectOutputStream(fos);
out.writeObject(rangeRandom);
out.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
RangeRandom rangeRandom2 = null;
FileInputStream fis = null;
ObjectInputStream in = null;
try
{
fis = new FileInputStream("test");
in = new ObjectInputStream(fis);
rangeRandom2 = (RangeRandom)in.readObject();
in.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
catch(ClassNotFoundException ex)
{
ex.printStackTrace();
}
}
}
如果執行 main,你將看到每個 RangeRandom 例項都執行了兩個執行緒,這是因為 Thread.start()
方法現在同時位於建構函式和 readObject()
中。