线程start() 和 run()的区别
start() 和 run()的区别:
首先需要知道线程的几个状态以及多线程工作方式。
- new 一个Thread,线程进入了新建状态,调用start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到 时间片 后就可以开始运行了。start() 会执行线程的相应准备工作,然后自动执行run() 方法的内容,这是真正的多线程工作。
- 而直接执行run() 方法,会把run 方法当成一个main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
总的来说:调用start 方法方可启动线程并使线程进入就绪状态,而run 方法只是thread 的一个普通方法调用,还是在主线程里执行。
线程生命周期(状态):
Java中线程状态6种:
NEW:新建
RUNNABLE:可运行/就绪
BLOCKED :阻塞
WAITING :等待/不见不散
TIMED_WAITING :超时等待/过时不候
TERMINATED:终止
注意:
BLOCKED/WAITING/TIMED_WAITING 这三种状态都不会获得CPU使用权
-
新建(new):新创建了一个线程对象。
-
可运行(runnable):线程对象创建后,当调用线程对象的 start()方法,该线程处于就绪状态,等待被线程调度选中,获取cpu的使用权。
-
运行(running):可运行状态(runnable)的线程获得了cpu时间片(timeslice),执行程序代码。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
-
阻塞(block):处于运行状态中的线程由于某种原因,暂时放弃对 CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被 CPU 调用以进入到运行状态。
阻塞的情况分三种:
阻塞状态(BLOCKED)
阻塞状态是指线程因为某种原因释放 cpu 使用权,也即让出了 cpu timeslice时间片,暂时停止运行。 直到线程进入可运行(runnable)状态,才有机会再次获得 cpu timeslice 转到运行(running)状 态。阻塞的情况分三种:
-
等待阻塞(o.wait->等待队列)
运行(running)的线程执行 o.wait()方法,JVM 会把该线程放入等待队列(waitting queue) 中。 -
同步阻塞(lock->锁池)
运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则 JVM 会把该线 程放入锁池(lock pool)中。 -
其他阻塞(sleep/join)
运行(running)的线程执行 Thread.sleep(long ms)或 t.join()方法,或者发出了 I/O 请求时, JVM 会把该线程置为阻塞状态。当 sleep()状态超时、join()等待线程终止或者超时、或者 I/O 处理完毕时,线程重新转入可运行(runnable)状态。
- 死亡(dead):线程run()、main()方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
深入理解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".
*/
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 */
}
}
}
//=============start0方法,是一个本地方法,底层是c实现的===============
private native void start0();
从整个方法上的注释看,start()使得该线程开始执行,Java虚拟机调用这个线程的run()方法,结果是两个线程会并发的运行:当前线程(调用start()方法的"主线程")与另一个线程(执行其run方法)
start()之后的代码的核心就是其中调用的start0()方法,下面看看start0()的定义:
private native void start0();
很明显这是一个只声明而未实现的方法,native表示调用本机的原⽣系统函数,native 方法往往意味着这个方法无法使用平台无关的手段来实现。所以,还是那句话,实际上线程的实现与 Java 无关,由平台所决定.
总结:
1、start()方法的具体流程:start方法(判断当前线程是不是首次创建,Java方法)->调用start0()方法(JVM)->通过JVM进行资源调度,系统分配->回调run()方法(Java方法)执行线程的具体操作任务。
2、由于start()方法调用了JVM进行系统调度、系统分配等一系列操作,因此创建一个线程只能由start()来完成,而若直接调用run()方法,相当于是在调用一个普通方法。
这个名字先用着: 说的很好。学到了
qq_40613940: 不太清晰
chazcn: 博主说得很详细了,谨补充一点拙见。 我曾经在大厂做生产管理,多次参与 WI 和 SOP 的编写。作为产线标准文档,WI 和 SOP 的主要区别在于: WI(作业指导)非常简洁,只写明简明操作流程,通常只有 1-2 页,在工位上封装悬挂,保证一个新上岗的员工能够看懂,在老员工的指导下,可以依照 WI 快速上手。 SOP(标准作业流程)的内容则需要相当详尽。 在操作指导部分,不仅要给出正常操作流程,还要对每个操作步骤进行详细说明,并注明其标准工时。 另外,就像博主整理的一样,SOP 需要涵盖物料说明、工具说明、设备基本操作说明、人员配置说明、安全作业规范等内容。 除此之外,SOP 还包含各种故障和其它突发状况的紧急处理方式,这也是 SOP 修订更新频率最高的部分。 总的来说,WI 是简明操作指导,可以帮助工人尽快上手;而 SOP 更像是速查手册,尽量包含该工序可能需要的所有信息。SOP 不需要工人逐字阅读,但生产中遇到问题时,工人及管理、技术人员都可以随时查阅。
2401_87361500: 您好,我能问一下R6那个是低电平输入还是高点平输入
Yigezxy: 强,放置个uuid