面试的时候被问到这个问题,当时懵懂了一下,答得不太好=。=,所以把源码翻来看看,总算是有所了解。
线程的实例化
线程在实例化的时候,并不能直接运行,而只是分配资源,其构造方法都会调用create方法:
/**
* Initializes a new, existing Thread object with a runnable object,
* the given name and belonging to the ThreadGroup passed as parameter.
* This is the method that the several public constructors delegate their
* work to.
*
* @param group ThreadGroup to which the new Thread will belong
* @param runnable a java.lang.Runnable whose method <code>run</code> will
* be executed by the new Thread
* @param threadName Name for the Thread being created
* @param stackSize Platform dependent stack size
* @throws IllegalThreadStateException if <code>group.destroy()</code> has
* already been done
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
Thread currentThread = Thread.currentThread();
if (group == null) {
group = currentThread.getThreadGroup();
}
if (group.isDestroyed()) {
throw new IllegalThreadStateException("Group already destroyed");
}
this.group = group;
synchronized (Thread.class) {
id = ++Thread.count;
}
if (threadName == null) {
this.name = "Thread-" + id;
} else {
this.name = threadName;
}
this.target = runnable;
this.stackSize = stackSize;
this.priority = currentThread.getPriority();
this.contextClassLoader = currentThread.contextClassLoader;
// Transfer over InheritableThreadLocals.
if (currentThread.inheritableValues != null) {
inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);
}
// add ourselves to our ThreadGroup of choice
this.group.addThread(this);
}
可见,这里只是完成线程相关变量的实例化,这是在堆中进行的,该线程位于当前线程组下。
start()
一般情况下,我们会调用start方法,即:
/**
* Starts the new Thread of execution. The <code>run()</code> method of
* the receiver will be called by the receiver Thread itself (and not the
* Thread calling <code>start()</code>).
*
* @throws IllegalThreadStateException - if this thread has already started.
* @see Thread#run
*/
public synchronized void start() {
//如果存在该线程,则会抛出异常
checkNotStarted();
hasBeenStarted = true;
nativeCreate(this, stackSize, daemon);
}
private native static void nativeCreate(Thread t, long stackSize, boolean daemon);
显然,start是真正调用底层的代码来创建thread,并从底层调用run()方法,执行我们自定义的任务。
run()
再来看一下run()干了什么:
/**
* Calls the <code>run()</code> method of the Runnable object the receiver
* holds. If no Runnable is set, does nothing.
*
* @see Thread#start
*/
public void run() {
if (target != null) {
target.run();
}
}
这里的target是初始化时候的runnable,可见这里,只是单纯调用runnable执行,而不是在子线程中运行,所以,当外部直接调用此方法时,相当于在当前线程执行任务,如遇到阻塞任务,也就会阻塞当前任务。
总结
run()只是在当前线程中执行任务,而start才是真正生成thread,并放在cpu中调度。