今天浏览到大牛的博客(https://blog.csdn.net/luoweifu/article/details/46673975)看到了线程部分,遂查资料记录。
Java提供了两种创建线程的方式,一种是实现Runnable接口,一种是继承Thread类。
首先用的时候就面临二选一问题,Java的话,自然是Runnable接口用的多一些,万一你写的类已经有了父类呢,Java单继承,多实现。
再说一下两者的关系。
Thread类本身实现了Runnable接口,所以无论用哪种方式,其实都是实现了Runnable接口。Runnable只有一个run方法,,最终线程执行时都是覆写的run方法。
上代码。
实现Runnable方法
package test;
public class ThreadA implements Runnable {
private Thread thread;
private String threadName;
public ThreadA(String threadName) {
thread = new Thread(this,threadName);//疑问点1
this.threadName = threadName;
}
@Override
public void run() {
for (int i = 0; i < 100; i ++) {
System.out.println(threadName + ": " + i);
}
}
public void start() {
thread.start();
}
}
继承Thread方法
package test;
public class ThreadB extends Thread {
private String threadName;
public ThreadB(String threadName) {
super(threadName);//疑问点2
this.threadName = threadName;
}
@Override
public void run() {
for (int i = 0; i < 100; i ++) {
System.out.println(this.getName() + ": " + i);
}
}
}
测试类
package test;
public class ThreadTest {
public static void main(String args[]) {
ThreadA threadA = new ThreadA("ThreadA");
threadA.start();
ThreadB threadB = new ThreadB("ThreadB");
threadB.start();
}
}
好,写出来创建线程的两种方法后,本着没有一行代码是废话的原则,开始理解每一行代码。发现了两个疑问点(在代码中有标)
疑问点1:
实现了Runnable接口的ThreadA类中的构造函数里thread = new Thread(this,threadName);为什么要传 this ?
经过查看API发现thread有好多构造函数(见下图),为什么偏偏要传this。
中文版
疑问点的构造函数具体解释
当我去掉this,只传线程名的时候,发现输出不了任何内容。
在看了API之后,告诉我很重要的一点。
首先明白,最终目的我们都要执行复写的run方法,那么如何找到run方法?就靠这个参数了,target - 其 run 方法被调用的对象。(这里也是之后写线程同步关键的地方!)
所以我去掉this不输出内容的原因是:找不到执行哪个run方法。
疑问点2:
继承了Thread的类ThreadB中的构造函数里为什么要加 super(threadName);
总所周知,super(); 是默认写出来的,需要显式的写出来的情况无非就是需要调用父类有参数的构造函数。所以这里为什么要把线程名给父类Thread?
super(threadName);去掉之后,run还是可以的,但是,线程名变成了自动分配的线程名,而非ThreadB线程名。所以super(threadName)实际上是给此线程起名。
网友评论