Démonstration de code :
/** * <p> * start() 和 run() 的比较 * </p> * * @author 踏雪彡寻梅 * @version 1.0 * @date 2020/9/20 - 16:15 * @since JDK1.8 */public class StartAndRunMethod { public static void main(String[] args) { // run 方法演示 // 输出: name: main // 说明由主线程去执行的, 不符合新建一个线程的本意 Runnable runnable = () -> { System.out.println("name: " + Thread.currentThread().getName()); }; runnable.run(); // start 方法演示 // 输出: name: Thread-0 // 说明新建了一个线程, 符合本意 new Thread(runnable).start(); } }复制代码
À partir de l'exemple ci-dessus Les deux points suivants peuvent être analysés :
L'utilisation directe de la méthode run
ne démarrera pas un nouveau fil de discussion. (Mauvais chemin) La méthode
start
démarre un nouveau fil de discussion. (Manière correcte)
start
la méthode peut être démarrée A nouveau fil.
start
après l'initialisation, le thread actuel (généralement le thread principal) demandera à la machine virtuelle JVM de démarrer ce nouveau thread ici s'il est libre. start
, nous ne pourrons peut-être pas démarrer le fil immédiatement. srtart
, cela ne signifie pas que cette méthode a commencé à s'exécuter. Il se peut qu'il ne fonctionne que plus tard, ou qu'il ne fonctionne pas pendant une longue période, par exemple en cas de famine. start
, puis le thread 2 appelle la méthode start
, pour constater que le thread 2 exécute d'abord le thread 1, puis s'exécute. start
sont appelées ne détermine pas l'ordre d'exécution réel du thread. start
La méthode impliquera deux threads. start
méthode, et le second est le nouveau thread . start
est déjà exécuté par le thread enfant. Cette instruction est en fait exécutée par le thread principal ou. le thread parent Exécuté, un nouveau thread sera créé après avoir été exécuté. start
Préparation à la méthode pour créer un nouveau fil
run
méthode. Remarque : La méthode de démarrage ne peut pas être exécutée à plusieurs reprises
Exemple de code
/** * <p> * 演示不能重复的执行 start 方法(两次及以上), 否则会报错 * </p> * * @author 踏雪彡寻梅 * @version 1.0 * @date 2020/9/20 - 16:47 * @since JDK1.8 */public class CantStartTwice { public static void main(String[] args) { Runnable runnable = () -> { System.out.println("name: " + Thread.currentThread().getName()); }; Thread thread = new Thread(runnable); // 输出: name: Thread-0 thread.start(); // 输出: 抛出 java.lang.IllegalThreadStateException // 即非法线程状态异常(线程状态不符合规定) thread.start(); } }复制代码
La raison de l'erreur
start
Une fois l'exécution démarrée, l'état du thread entrera dans l'état suivant à partir de l'état initial New, tel que Runnable, puis une fois le le thread termine l'exécution, le thread deviendra un état terminé et l'état terminé ne pourra jamais être renvoyé, donc l'exception ci-dessus sera levée, ce qui signifie qu'il ne peut pas revenir à l'état initial. La description ici n'est pas assez claire, regardons le code source pour mieux comprendre. 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 方法 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 */ } } }复制代码
Étape 1 : Lors du démarrage d'un nouveau thread, il vérifiera d'abord si l'état du thread est l'état initial, ce qui est également la raison pour laquelle l'exception ci-dessus est levée. C'est-à-dire le code suivant :
if (threadStatus != 0) throw new IllegalThreadStateException();复制代码
L'annotation de cette variable threadStatus
est la suivante, ce qui signifie que l'état du thread Java est initialement exprimé par 0 (pas encore démarré) :
/* Java thread status for tools, * initialized to indicate thread 'not yet started' */private volatile int threadStatus = 0;复制代码
Étape 2 :Ajoutez-le au groupe de discussions. C'est à dire le code suivant :
group.add(this);复制代码
La troisième étape : Enfin appeler la start0()
méthode native (native signifie que son code n'est pas implémenté par Java, mais par C/C++, L'implémentation spécifique peut être vue dans le JDK, il suffit de le comprendre), c'est-à-dire le code suivant :
boolean started = false;try { // 第三步, 调用 start0 方法 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 */ } }复制代码
@Overridepublic void run() { // 传入了 target 对象(即 Runnable 接口的实现), 执行传入的 target 对象的 run 方法 if (target != null) { target.run(); } }复制代码
La première : la méthode Thread
de la classe run
est remplacée, la méthode Thread
de run
sera invalide, et la méthode run
Deuxième type : transmettre l'objet target
(c'est-à-dire l'implémentation de l'interface Runnable
), exécuter la méthode Thread
originale de run
puis exécuter le target
Méthode run
de l'objet.
Résumé : La méthode
run
est une méthode ordinaire Exécuter directement la méthode run
ci-dessus équivaut à exécuter ce que nous écrivons nous-mêmes. Identique à la méthode ordinaire, son thread d'exécution est donc notre thread principal. run
, mais vous devez appeler la méthode start
, qui peut appeler indirectement la méthode run
. Recommandations d'apprentissage associées : bases de Java
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!