记一则 Thread 与 Runnable区别

2021-04-16  本文已影响0人  秋名山吴师傅

最近重拾java进行学习。在学到Thread多线程的时候,demo给出了Thread与Runnable两种实现方式

Thread

public class ThreadAndRunnableDiff {
    public static void main(String[] args) {
        // 创建Thread进程
        Thread t = new MyThread();
      // 线程启动加入等待执行队列
        t.start();
    }
    public static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("This is the thread, priority is:"+getPriority());
        }
    }
}

Runnable

public class ThreadAndRunnableDiff {
    public static void main(String[] args) {
        Runnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
    }
    
    public static class MyRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println("This is the runnable priority is");
        }
    }
}

我们从以上示例可以看出来两者有区别,但是写法上区别似乎并不大。
Thread是直接new然后调用start方法,而Runnable是通过Thread类进行调用start

角度 Thread Runnable
本质 接口
方法 拥有start方法和run方法 只有run方法
创建一个唯一的对象并与之关联 多个线程共用一个对象
内存 由于多个线程的对象对立所以内存占用比Runnable方式少 由于通过Thread类创建的线程都是可以共用一个Runnable对象所以内存占用比Thread少
使用上的限制 由于Thread是要通过继承而来,而JAVA不支持多继承,所以一旦继承了Thread类后子类不允许再继承别的类 Runnable由于是接口,JAVA是允许多实现的,所以Runnable使用上的多样性会比Thread要更多

源码本质区别

Thread

一般使用Thread的方式,我们是通过继承Thread类,并重写其run方法,我们来看看Thread构造干了什么 以我们Thread的代码例子来说

1. new Thread()

调用了Thread的构造我们来看看他的构造干了什么?

public Thread() {
        this(null, null, "Thread-" + nextThreadNum(), 0);
    }

看到他调用了当前的重载方法,传入了(null, null, "Thread-" + nextThreadNum(), 0)四个参数,我们继续追踪

2.Thread(null, null, "Thread-" + nextThreadNum(), 0)

 public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
        this(group, target, name, stackSize, null, true);
    }

我们可以看到
这个类参数注入了ThreadGroup,Runnable两个对象,我们继续追踪

3. private Thread(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals)

private Thread(ThreadGroup g, Runnable target, String name,
        ........
  this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        .....
    }

关键在于 this.target = target;
其实Thread最终还是内部转化成Runnable并设置到类属性 this.target中

4. 线程启动 start方法

这里就一个重点方法调用start0

5. 调用start0方法

6. 重点来了run方法

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

由于上面target是由于Runnable注入,所以这里最终就是调用target.run方法

所以我可以认为,Thread最终还是会内部转化为Runnable方法进行调用

由于我JAVA也是刚开始熟悉底层也不知道对不对还望各位看客多多提点

上一篇下一篇

猜你喜欢

热点阅读