Runnable和Thread源码分析

本文深入分析了Java中Runnable和Thread的源码,揭示了start()方法启动线程而非run()的原因。通过对比Runnable和Thread实现线程的不同方式,解释了run()方法在Thread类和Runnable接口中的作用。通过实例展示了如何在Thread中执行Runnable的run()方法,并探讨了多线程资源共享的问题,建议在多线程应用中优先考虑使用Runnable实现线程共享资源。
摘要由CSDN通过智能技术生成

Runnable和Thread源码分析

问题的引入
Runnable是一个接口,它只有一个run()抽象方法,run()抽象方法需要被实现后才能使用。Thread类继承了Runnable接口,并且Thread中实现了run()方法。最后,通过Thread类的start()方法就可以启动线程了。这是我们平时在应用中使用线程的常用方法。如果多加思考你会发现以下几个问题:
1、为什么调用start()方法就可以启动线程,而不是调用run()。start()方法和决定线程运行内容的run()方法又有什么联系呢?
2、在Runnable层面实现run()方法和Thread层面实现run()方法的区别。
3、怎么用Runnable实现run方法,并在Thread中执行Runnable实例化后重写的run方法。
不着急下结论,我们通过分析源码来理清两者的关系。
Runnable源码
打开如下Runnable的源码,我们可以发现,它只含有一个抽象的run()方法。因为它是接口,所以需要被继承后重写run()方法才能使用。我们可以简单思考一下,如果需要启动一个新的线程,这意味着需要分配给它CPU资源来执行这个线程,而CPU是不归JVM(Java虚拟机)直接管辖的,自然需要通过JVM通过外部的接口来实现和操作系统的对话,调整CPU资源的分配,所以,线程的创建一定是一个native方法(实现Java调用底层的C、C++代码)。接口中的run()方法中的内容,仅仅代表线程运行的内容。一个结论出来了,Thread类中必然有native方法,Runnable无法脱离Thread类来新建线程。如果我们在new一个线程对象后直接调用run方法,也只是让当前线程去执行run()方法中的语句罢了,并没有实现多线程。

public interface Runnable {
   
    public abstract void run();
}

Thread源码
接下来我们看看Thread类的源码。
从下面这句我们可以看出Thread继承了Runnbale接口。

public class Thread implements Runnable {
   

下面是Thread类的run()方法。里面的target对象是什么?为什么target能调用run()方法?这个run()方法是谁的run()方法?

    @Override
    public void run() {
   
        if (target != null) {
   
            target.run();
        }
    }

为了解决问题,我们把关注点放到Thread类的这几行代码上。在Thread类的一个构造方法中Runnable接口的实例化对象target被传入其中,通过几个方法的调用,并通过this.target = target;语句把Runnable的实例化对象保存在了Thread类中,成为了Thread类的一个成员变量,那么它调用的run()方法自然是在Runnable实例化中重写的run()方法。

    private Runnable target;
    public Thread(Runnable target) {
   
        init(null, target, "Thread-" + nextThreadNum(), 0);        
    }    
   private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
   
        <
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值