并发基础之正确启动多线程,并发多线程
并发基础之正确启动多线程,并发多线程
start方法和run方法比较
很多人包括我自己也以前也认为run和start方法都可以启动一个线程,并且两者的功能都差不多,然后在学习的过程中认识到这是错误的,他们之间是截然不同的。先来看一段演示代码:
/**
* @author Chen
* @Description start()和run()方法比较
* @create 2019-11-05 22:01
*/
public class StartAndRunMethod {
public static void main(String[] args) {
//使用run方法
Runnable runnable = ()-> System.out.println(Thread.currentThread().getName());
runnable.run();
//使用start方法
new Thread(runnable).start();
}
}
输出结果:
main
Thread-0
可以看到,执行run方法的线程是主线程,而执行start方法的才是一个新的子线程。
start方法解读
我们都知道start方法就是启动一个新线程,其实真是情况是start方法执行过程中会涉及到两个线程,一个是主线程,另一个是新的子线程,当调用start方法是,子线程并不会马上启动起来,子线程会获取除了cpu以外的一些资源,进入就状态,等待CPU的调用。至于什么时候调用,这个就不是我们所能决定的了,而是线程调度器来决定的。所以有一些先运行start方法的线程可能会在比后调用start方法的线程启动的慢。
当我们重复调用两次start方法会发生什么?
会抛出一个异常IllegalThreadStateException(非法的线程状态),其实线程一旦执行,就会进入runnable状态,一旦执行完毕,就会进入结束状态,不会在返回回去。
接下来我们在来仔细看看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".
*/
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 */
}
}
}
在start()
中,首先会检查线程的状态,判断threadStatus
是不是等于0,也就是判断是不是一个新启动的线程,这是执行两次start()
抛出异常的原因。(在线程刚刚被初始化的时候默认的状态为0)
然后又做了一个加入线程组这个行为,然后又执行了个start0的native方法。
run方法解读
其实run方法比较简单,只有三行代码:如果target也就是传入的接口不为空,就执行重写的run方法的内容,否则就执行传入的run方法的内容。
@Override
public void run() {
if (target != null) {
target.run();
}
}
所以当我们执行run方法的时候,它就会作为一个普通的方法,和我们自己写的一样,所以控制台打印出来的是一个主线程。
所以我们想启动一个新线程不能直接调用run方法,而是应该调用start方法来间接调用run方法。
相关文章
- 暂无相关文章
用户点评