这篇文章的代码都是不完整的伪代码,只是为了说明问题截取出来的,切记切记!!!
实现线程的两种方式:
- class MyThread extends Thread类 { }
class MyThread extends Thread {
@Override
public void run() {
//自己写代码
}
}
- class MyThread implements Runnable { }
class MyThread implements Runnable {
@Override
public void run() {
//自己写代码
}
}
- 用 main()函数测试多线程:
public class Demo {
public static void main(String[] args) {
Thread t = new Thread( new MyThread() ); //只是为了说明问题,这里就不创建两个对象了
t.start(); // 调用start()方法
}
}
不管用哪种办法实现多线程,都是调用了Thread类的start()方法,然后我 Ctrl + 左键单击 查看了 start()方法的实现
下面列出了部分我觉得重要的属性和方法:
// Runnable接口的内容:只有一个abstract的run()方法等待实现了此接口的类去具体书写 public interface Runnable { public abstract void run(); }
// Thread类的部分内容:
public class Thread implements Runnable { // 首先Thread类实现了Runnable接口,则必有run()方法的实现
private volatile String name; // 线程的name属性
/* What will be run. */
private Runnable target; // Runnable类型的target属性???干什么用的呢???/* The group of this thread */
private ThreadGroup group; // 线程组group属性public Thread(String name) { // 其中一个构造方法,发现创建一个线程时,调用了init()方法
init(null, null, name, 0);
}private void init(ThreadGroup g, Runnable target, String name.....) { // init()方法的部分内容
this.name = name; // 把线程的名字赋给name属性
........
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();........
this.target = target; // 把传入的new MyThread()赋给target???
}public synchronized void start() { // 找到了Thread对象调用的start()方法
group.add(this); // group属性在这里使用,把当前对象加入到线程组
boolean started = false; // 标记线程的一个状态
try {
start0(); // start0()方法用来启动线程
started = true;
} finally {
.............
}
}private native void start0(); // start0()在这里,为什么是这样的?native是与C++联合开发的时候用的(下面解释)
@Override
public void run() { // 实现了Runnable接口的唯一run()方法
if (target != null) {
target.run(); // 如果target属性不为空,就调用target的run()方法。???
}
}public final String getName() {
return name; // 用getName()能得到线程名字
}
}
native 关键字 表示这个方法是原生函数: native关键字的函数都是操作系统实现的
也就是说native 后的函数的实现不是用java写的。
也就是说这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。
Java无法直接访问到操作系统底层,可以将native方法比作Java程序同C程序的接口
读了Thread类的内容后我还是很迷糊:
我们在main函数中调用的一直都是Thread类的start()方法啊,这个run()方法是怎么工作的呢?
既然start0()是c/c++写的,那也不容易去研究这个方法的实现了,可是
既然Thread类中重写了Runnable接口的run()方法,但他是怎么调用的呢?
分析:
class MyThread extends Thread {
- 自己创建的MyThread类要么直接实现Runnable接口,要么继承Thread类间接实现Runnable接口
@Override
public void run () {
//自己写代码
}
}
- main函数创建Thread对象时 有时会传入一个 实现了Runnable接口并重写了run()方法 的实例对象
public static void main(String[] args) {
Thread t = new Thread( new MyThread( ) );
}
- 但不论哪种构造方法都会调用init()函数
public Thread(String name) {
init(null, null, name, 0); // 这个构造函数没有传入参数 target,给init()函数传值为null
}public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0); // 构造函数会把target对象传给init()函数
}
- 在init()函数中会把传入的Runnable对象赋给 this.target 属性
private void init(ThreadGroup g, Runnable target, String name.....) {
this.target = target;
}
- start()方法实际上是通过本地方法start0()方法启动线程的
public synchronized void start() {
start0(); // start0()会新运行一个线程,新线程会调用run()方法。
}
- run()方法会直接调用Thread线程的Runnable成员的run()方法,并不会新建一个线程。
public void run() {
if (target != null) {
target.run();
}
}
- 调用start()方法和直接调用run()方法的区别:
Thread.currentThread().getName()是用于获取“当前线程”的名字。当前线程 是指正在cpu中调度执行的线程。
单独调用run()的话:会在当前线程中执行run()方法(主线程main),并不会启动新线程:
调用start()方法会启动一个新线程:"t2"线程,并在新线程"t2"中运行run()方法:
- 新建线程应该是 start0()函数完成的操作!!!