Java线程序列化,为什么序列化的线程对象可以启动

Abh*_*ary 7 java serialization

java中的一个线程无法在Java中重启,所以我实现了一个java Thread,然后在获取Thread的序列化对象后尝试重启该线程.

import java.io.Serializable;

public class ThreadSerialization extends Thread implements Serializable {

    int iCheck = 10;
    @Override
    public void run() {
        System.out.println("STARTING");
        for(int i=0;i<10;i++){
            iCheck+=i;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

和序列化算法 -

public class CallingThreadSerializable {

    public static void main(String[] args) {
        ThreadSerialization ser = new ThreadSerialization();
        ser.start();
        FileOutputStream fos = null;
        ObjectOutputStream out = null;
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fos = new FileOutputStream("thread.ser");
            out = new ObjectOutputStream(fos);
            out.writeObject(ser);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try {
            fis = new FileInputStream("thread.ser");
            ois = new ObjectInputStream(fis);
            ThreadSerialization ser1 = (ThreadSerialization) ois.readObject();
            System.out.println("---> " + ser1.iCheck);
            ser1.start();
            System.out.println("---> " + ser1.iCheck);
            ois.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

输出 -

STARTING
---> 55
---> 55
STARTING
Run Code Online (Sandbox Code Playgroud)

为什么ser1对象再次启动?

A.H*_*.H. 16

有两点:

第一:Thread不是Serializable,因此serializableJavaDoc 的以下摘录适用:

为了允许序列化非可序列化类的子类型,子类型可以承担保存和恢复超类型的公共,受保护和(如果可访问)包字段的状态的责任.

这意味着,您的班级ThreadSerialization将有责任存储和恢复状态Thread.但由于很多private领域,你不能这样做Thread.因此,所有私有字段Thread都默认初始化.现在看看实施Thread.start():

    //...
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    // ...
    start0();
    //...
Run Code Online (Sandbox Code Playgroud)

由于threadStatus尚未正确存储/恢复,您可以再次启动.

第二:不要混淆实际的操作系统线程和"管理器"对象java.lang.Thread- 它们只是松散耦合.在您的示例中,您只序列化管理器,但不序列化在Java中没有表示的OS线程.反序列化后,您有第二个管理器实例,没有附加OS线程.所以告诉经理开始会成功.


Jiv*_*ngs 8

如果你反序列化(?)一个Object,那么你实际上是在创建一个具有与原始Object相同属性的新类实例.

它不是同一个对象.

同样,由于Thread本身不实现Serializable,因此启动性实际上是任何Serializable子类中的瞬态状态的一部分(因为中断),因为序列化不会恢复从非Serializable超类继承的字段.任何类extends Thread implements Serializable,假设有一个很好的理由这样做的所有,也许应该有自己的领域来跟踪startedness和interruptedness,并调用Thread.start()Thread.interrupt()readObject()readResolve()恢复其状态的那些元素.