之前写了好几篇文章,对目前自己的水平来说都比较勉强,脑细胞死掉很多。今天,本文来聊简单一点的,轻松加愉快的话题,那就是Thread和Runnable之间的关系。为什么要说这个因为平时自己很喜欢无脑用这两个东西来开线程运行,但是从来没想过它俩关系这个问题,既然想到了就得来探究下。
1、开线程的用法
关于Thread和Runnable开线程用法,我是比较喜欢的,上代码。
new Thread(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext,"this is a test for thread and runnable",Toast.LENGTH_SHORT).show();
}
}).start();
就这么轻松加愉快一个创建了一个线程并运行了起来,这里创建的是Thread对象,而Runnable对象是传参。
2、父子关系
如本小节题目点出的那样,Thread和Runnable之间是父子关系,由Thread的源码可以看出,Thread是对Runnable的实现,先看看Runnable的源码吧
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
太简单了,就一个抽象run方法,于是乎Thread实现Runnable就只需要实现这个run方法就行,看代码
@Override
public void run() {
if (target != null) {
target.run();
}
}
而这里的target就是我们传入的new Runnable的实现,这个从Thread类的初始化方法可以看到
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
Thread parent = currentThread();
if (g == null) {
g = parent.getThreadGroup();
}
g.addUnstarted();
this.group = g;
this.target = target;
this.priority = parent.getPriority();
this.daemon = parent.isDaemon();
setName(name);
init2(parent);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
tid = nextThreadID();
}
3、start方法如何调用起异步线程
关于这一小节我只能说一点都不愉快了,一开始我知道,最后肯定要调用到传参实现的run方法的,而这个run方法在Thread类中是通过Thread类的run方法来调用的(可见以上代码)。但是实际上,我们实例化Thread对象后,调用的是start方法,那么再来跟踪下这个start方法。
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
// Android-changed: throw if 'started' is true
if (threadStatus != 0 || started)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
started = false;
try {
nativeCreate(this, stackSize, daemon);
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 */
}
}
}
看代码只有nativeCreate方法有可能调用到run方法上面去,于是接着跟却发现这个方法是一个native方法
private native static void nativeCreate(Thread t, long stackSize, boolean daemon);
带Thread类里没有具体的实现,这个就给我出难题了,这个肯定涉及到了更底层的东西了,而关于新线程的创建肯定也是在更底层完成的,这个我没啥时间去探究,关于JNI和NDK这两块知识点也了解的不深,这个就暂时放下,今天算是点个技能树在这里,有进一步研究的同学可以看下面这篇文章。
了解Java线程的start方法如何回调run方法:
http://blog.csdn.net/itmyhome1990/article/details/78471653
当然以后我有时间一定会回来的,本文目前就这么愉快的结束吧。