最近重拾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也是刚开始熟悉底层也不知道对不对还望各位看客多多提点
网友评论