Runnable与Thread没有根本性的区别,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();
}
Thread是实现了Runnable接口,添加了更多的方法和属性
public
class Thread implements Runnable {
/* Make sure registerNatives is the first thing <clinit> does. */
private static native void registerNatives();
static {
registerNatives();
}
private volatile char name[];
private int priority;
private Thread threadQ;
private long eetop;
/* Whether or not to single_step this thread. */
private boolean single_step;
/* Whether or not the thread is a daemon thread. */
private boolean daemon = false;
/* JVM state */
private boolean stillborn = false;
/* What will be run. */
private Runnable target;
/* The group of this thread */
private ThreadGroup group;
/* The context ClassLoader for this thread */
private ClassLoader contextClassLoader;
/* The inherited AccessControlContext of this thread */
private AccessControlContext inheritedAccessControlContext;
/* For autonumbering anonymous threads. */
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
... ...
... ...
而网上部分观点说Runnable可实现资源共享也是有误的
Thread的run()与start()方法
run方法是执行了super.target的run()方法,而start()方法才是创建了一系列过程,最后通过native方法start0()回调回重写的run方法,以下是Thread源码中的两个方法的源码
@Override
public void run() {
if (target != null) {
target.run();
}
}
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".
*/
if (threadStatus != 0)
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);
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 */
}
}
}
其中主要三步:判断线程状态、加入线程组、执行native方法start0()
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
//初始状态就是为0
private volatile int threadStatus = 0;
start() 是一个 synchronized 方法,但为了避免多次调用,在方法中会由线程状态判断。threadStatus != 0。在new Thread时会被初始化为0
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
而threadStatus是在线程从创建到结束生命周期中,由JVM控制的,如下:
public State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
状态有以下几种:
VM.class
public static State toThreadState(int var0) {
if ((var0 & 4) != 0) {
return State.RUNNABLE;
} else if ((var0 & 1024) != 0) {
return State.BLOCKED;
} else if ((var0 & 16) != 0) {
return State.WAITING;
} else if ((var0 & 32) != 0) {
return State.TIMED_WAITING;
} else if ((var0 & 2) != 0) {
return State.TERMINATED;
} else {
return (var0 & 1) == 0 ? State.NEW : State.RUNNABLE;
}
}
以上是按位与计算的,也就是二进制位置对其,都为1时才为1,否则为0,eg:var0 & 1 ==0 =>0&1=0,则标识var0当前状态为0.
如果threadStatus=0初始化状态,则加入线程组,默认初始数组长度为4。一个线程必须有自己所属的线程组,且一但加入则不能更改,加入线程组可以方便管理线程,比如设置优先级、守护线程等。
/* The group of this thread */
private ThreadGroup group;
最后执行本地方法start0()。(一般java底层方法名带0的都是native方法)这一步的操作才是启动线程的核心步骤。后续都是jvm代码了,不做展开。
线程创建到执行的过程简单描述如下:
1、Java 创建线程和启动;
2、调用本地方法 start0();
3、JVM 中 JVM_StartThread 创建和启动Thread;
4、设置线程状态等待被唤醒;
5、根据不同的OS启动线程并唤醒;
6、最后回调 run() 方法启动 Java 线程。
实现案例
1、继承Thread,并重写start方法,调用start即可
public class ThreadA extends Thread {
@Override
public void start(){
System.out.println("ThreadA");
}
}
调用start的
2、实现Runnable接口,重写run方法并调用run方法触发
public class RunnableA implements Runnable {
@Override
public void run() {
System.out.println("RunnableA");
}
}
以上执行demo如下
public class Test {
public static void main(String[] args) {
ThreadA threadA = new ThreadA();
RunnableA runnableA = new RunnableA();
threadA.start(); //打印结果:ThreadA
runnableA.run(); //打印结果:RunnableA
}
}