Thread类作为对象,其本身具有的功能是顺序执行指定功能(run()方法,即普通的函数功能)和异步执行指定功能(start()方法,在不阻塞后续代码执行的同时,执行自身的run()方法,即多线程特性,开启新线程来执行该方法)。对应的接口为Runnable。构造函数有如下形式:

Thread()
Allocates a new Thread object.
Thread(Runnable target)
Allocates a new Thread object.
Thread(String name)
Allocates a new Thread object.
Thread(ThreadGroup group, Runnable target)
Allocates a new Thread object.
Thread(ThreadGroup group, String name)
Allocates a new Thread object.
Thread(Runnable target, String name)
Allocates a new Thread object.
Thread(ThreadGroup group, Runnable target, String name)
Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group.
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group, and has the specified stack size.

总结一下不难发现,所有的构造函数都可以看作最后一个的变形,ThreadGroup可视作管理线程用的线程组对象,name和stackSize可视作对该线程对象的属性的设置。私以为这个Runnable的target是其中的重中之重。虽然理解之后看来理所应当,但是还是在此做下记录。初学者()在看到这里之时,很有可能忘记这个Runnable的本质是个Interface,仅仅是个对传入对象做出功能要求的接口罢了,因而,target本身是个对象,可以理解为,在给一个新建的Thread对象传入一个Runnable的实体对象的时候,再调用start()方法时,是调用的该对象——target的方法。

我为何要再此如此强调“该对象”呢?起缘于我在学习java的多线程编程时,看到的一个关于死锁的示例。

详情可参见 https://blog.csdn.net/nightcurtis/article/details/78532818

其中这段代码让我当时心生疑惑:

    ....
    public static void main(String args[]) throws Exception {
        DeadLock dl=new DeadLock();
        new Thread(dl).start();
        dl.init();
    }
}

根据设计的逻辑,同时调用两个不同对象、相互引用对方的synchronized方法的话,会因为双方都企图在不释放自己的线程锁的同时去调用对方上锁的方法,双方都不肯释放自己的对象锁,导致无限等待,即出现死锁现象。(synchronized方法的默认锁是对象本身,即this

但是,你这里不是拿Thread新建了一个对象吗?按理说你这是两个不同对象调用各自的方法,怎么会锁上呢?

“实践是检验真理的唯一标准”。实践过后,发现还真他丫的锁上了。然后反过来开始找自身理论出现的问题。在之前我对new Thread(dl).start();这一段的理解是,会创建一个与dl一样的新对象,并异步执行其run()方法。事实上,传进去的是一个对象,在Thread的实现代码里也没看见有target.getClass().newInstance()这种神奇操作,创建新对象的可能性自然不大。况且,若是创建新对象的话,也不一定非要指定一个RunnableInterface,这Runnable接口的本身不就是为了让该对象有一个能够用于多线程执行的方法吗?

则对于java.lang.Thread类的本次理解,有总结如下:向Thread类的构造函数传入一个Runnable的实体对象后,将会产生一个可视作其run()函数与该对象相同的线程对象,其上下文就是传入的对象的上下文,并不是创建一个全新的对象。

标签: none

添加新评论