jdk源码笔记,备忘
1.开启一个线程中间到底发生了什么
class MyThread extends Thread{
public void run(){
}
public static void main(String[] args) {
MyThread t1=new MyThread();
t1.start();
}
};
1.调用父类Thread的构造函数,其中init方法比较重要
其中的线程的tid和线程的名称都是使用的内存加锁自增
private static synchronized long nextThreadID() { return ++threadSeqNumber; }
2.t1.start(),调用的是父类的start()方法
public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } }
threadStatus 就是上节课描述的状态,默认是0,只能调用一次,再次调用就不是0了,所以报错,因为线程只能启动一次
start0() 真正的启动线程,是一个native方法
线程启动完成后,jvm底层会调用我们MyThread的重新的run方法,这是一个线程的大致过程
3.假如我们调用t1.run();会发生什么呢
会发生方法调用,因为我们重写了父类Thread的run方法,并且可以多次调用,如下
@Override public void run() { if (target != null) { target.run(); } }
4.MyThread extends Thread 有一个缺点,因为java单继承,那假如我们有一个类并且有父类,那如何办呢?这个时候就出现了runnable这个接口,博主认为runnable是解决这个问题实现的,并不是用来替代Thread的
下面 就来看看runnable如何解决这个问题。
new Thread(我们自己的runnable子类).start();
public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
target就是我们传进来的子类的实例
start(),调用的是Thread的start()方法,同继承Thread一样
不一样的是回调方法:回调的是Thread的run方法,
target就是我们传进来的runnable子类,然后执行子类的run方法
@Override public void run() { if (target != null) { target.run(); } }
那假如调用 new Thread(我们自己的runnable子类).run();又会发生什么呢
调用的就是Thread的run方法
runnable子类,然后执行子类的run方法
@Override public void run() { if (target != null) { target.run(); } }