需要一些关于Java线程的说明:start()和run()

需要一些关于Java线程的说明:start()和run(),java,multithreading,Java,Multithreading,根据StackOverflow的回答,start创建一个线程并在这个新线程中执行代码,而run在当前线程中执行代码,而不创建任何线程,就像它是一个可运行的线程一样 但是文档,如果我理解正确的话,会说start初始化一个新线程,然后,如果你想在同一个线程中重新执行你的代码,你可以调用run 哪一个是对的 UPD 好的,看起来手动调用run不是一个好的做法,至少是没有用的。有什么好方法可以在运行时调用代码吗?比如说,我经常需要一个相对缓慢的动作,一次一个实例——然后呢?如前所述,这两个动作都不对 s

根据StackOverflow的回答,start创建一个线程并在这个新线程中执行代码,而run在当前线程中执行代码,而不创建任何线程,就像它是一个可运行的线程一样

但是文档,如果我理解正确的话,会说start初始化一个新线程,然后,如果你想在同一个线程中重新执行你的代码,你可以调用run

哪一个是对的

UPD

好的,看起来手动调用run不是一个好的做法,至少是没有用的。有什么好方法可以在运行时调用代码吗?比如说,我经常需要一个相对缓慢的动作,一次一个实例——然后呢?

如前所述,这两个动作都不对

start不会创建或初始化线程。它开始一条线。发件人:

使该线程开始执行;Java虚拟机调用此线程的run方法

线程是通过调用线程构造函数来创建和初始化的,当然在调用start之前必须这样做。不管怎么说,这就是外部神话;我必须检查JVM规范,但我怀疑JVM将操作系统线程的实际创建推迟到调用start之前(除非调用start),这可能是有效的

在正常情况下,您永远不会直接调用线程实例的run方法。相反,您可以通过start启动线程,JVM会安排调用在分配给该线程实例的实际线程上运行。如果您直接调用run,它将在用于执行该操作的线程上被调用,而该线程可能不是分配给线程实例的线程

你可能会发现这本书很有用

下面是您的评论:

如何在运行中重新执行代码?重新启动线程或使用一个布尔值控制执行的无限循环

后者,但不是无限循环,是具有终止条件的循环。从文档开始:

多次启动线程是不合法的。特别是,线程一旦完成执行,就不能重新启动

所以一旦run返回,就不能继续使用线程了。相反,在线程的工作完成之前,线程不会从运行中返回。如果您想让它一直等待工作,它应该等待某种信号量,您可以从线程外部发出信号,唤醒它来做一些工作

上面教程的一个小节讨论了使用wait和notify/notifyAll实现这一点的一种方法

下面是一个简单的示例,其中对System.out.println的每次调用都会打印进行调用的线程的名称,以便您可以看到哪个线程执行以下操作:

示例输出:

main: Running main main: Calling t.start() main: Calling t.join() to wait for thread exit Thread-0: Running run main: Program complete 请注意,我们的主线程只调用start;然后JVM进行设置,以便在我们创建的线程上调用run。

如前所述,两者都不对

start不会创建或初始化线程。它开始一条线。发件人:

使该线程开始执行;Java虚拟机调用此线程的run方法

线程是通过调用线程构造函数来创建和初始化的,当然在调用start之前必须这样做。不管怎么说,这就是外部神话;我必须检查JVM规范,但我怀疑JVM将操作系统线程的实际创建推迟到调用start之前(除非调用start),这可能是有效的

在正常情况下,您永远不会直接调用线程实例的run方法。相反,您可以通过start启动线程,JVM会安排调用在分配给该线程实例的实际线程上运行。如果您直接调用run,它将在用于执行该操作的线程上被调用,而该线程可能不是分配给线程实例的线程

你可能会发现这本书很有用

下面是您的评论:

如何在运行中重新执行代码?重新启动线程或使用一个布尔值控制执行的无限循环

后者,但不是无限循环,是具有终止条件的循环。从文档开始:

多次启动线程是不合法的。特别是,线程一旦完成执行,就不能重新启动

所以一旦run返回,就不能继续使用线程了。相反,在线程的工作完成之前,线程不会从运行中返回。如果您想让它一直等待工作,它应该等待某种信号量,您可以从线程外部发出信号,唤醒它来做一些工作

上面教程的一个小节讨论了使用wait和notify/notifyAll实现这一点的一种方法

下面是一个简单的示例,其中对System.out.println的每次调用都会打印进行调用的线程的名称,以便您可以看到哪个线程执行以下操作:

示例输出:

main: Running main main: Calling t.start() main: Calling t.join() to wait for thread exit Thread-0: Running run main: Program complete
请注意,我们的主线程只调用start;然后JVM进行设置,以便在我们创建的线程上调用run n启动并运行:

:当程序调用start方法时,Java虚拟机将调用此线程的run方法

:若直接调用run方法,run中的代码将在当前线程上执行


以下是启动和运行之间的主要区别:

:当程序调用start方法时,Java虚拟机将调用此线程的run方法

:若直接调用run方法,run中的代码将在当前线程上执行

如果我正确理解了它们,比如说start初始化了一个新线程,那么,如果你想在同一个线程中重新执行你的代码,你可以调用run

这是不正确的。您需要了解,每个Java程序都是从主线程开始执行的。换句话说,当您运行一个具有main方法(例如javamyprogram)的Java程序时,将使用该堆栈底部的main方法创建一个新的执行堆栈

如果程序在main方法中创建了一个线程实例,并在线程实例上调用start方法,那么将使用堆栈底部的run方法创建一个新的执行堆栈。现在将有两个执行堆栈。一个在堆栈底部使用main方法,另一个在堆栈底部使用run方法。这两个堆栈可以并行执行

另一方面,如果改为在main方法中调用run On线程实例,它将在与main方法相同的执行堆栈中被调用。将不会创建新的执行堆栈。因此,在线程实例上调用run与在任何其他对象上调用任何其他方法一样,没有特殊意义

如果我正确理解了它们,比如说start初始化了一个新线程,那么,如果你想在同一个线程中重新执行你的代码,你可以调用run

这是不正确的。您需要了解,每个Java程序都是从主线程开始执行的。换句话说,当您运行一个具有main方法(例如javamyprogram)的Java程序时,将使用该堆栈底部的main方法创建一个新的执行堆栈

如果程序在main方法中创建了一个线程实例,并在线程实例上调用start方法,那么将使用堆栈底部的run方法创建一个新的执行堆栈。现在将有两个执行堆栈。一个在堆栈底部使用main方法,另一个在堆栈底部使用run方法。这两个堆栈可以并行执行


另一方面,如果改为在main方法中调用run On线程实例,它将在与main方法相同的执行堆栈中被调用。将不会创建新的执行堆栈。因此,在线程实例上调用run与在任何其他对象上调用任何其他方法一样,没有什么特殊意义。

您的困惑可能来自对术语thread、create和initialize的模糊使用。如果不具体说明它们具体解决了什么问题,那么很容易被误解,因为线程这个术语用来描述多个概念

一方面,存在通过新线程创建的线程对象。。。构造器。这不是实际执行任何事情的线程。它只是线程机制的一个门面,线程机制实现了与OS/VM交互的标准化API

仅仅创建一个线程实例与创建任何其他java对象基本上没有什么不同。现在还没有发生任何与向OS线程调度程序实际添加线程有关的事情

操作系统端的线程实际上是在私有本机方法start0中创建的,start方法执行一些健全性检查,然后调用start0来实际创建操作系统级线程

因此,行动的一般顺序是:

创建并初始化线程对象 还没有什么不寻常的事情发生 在上面的线程对象上调用start 委托本机代码以创建操作系统级线程。操作系统级线程的入口点是java端的thread.run。 在新线程上执行Thread.run,默认执行对创建线程对象时使用的Runnable的运行委托,或者如果没有Runnable,则不执行任何操作
您的困惑可能来自对术语thread、create和initialize的模糊使用。如果不具体说明它们具体解决了什么问题,那么很容易被误解,因为线程这个术语用来描述多个概念

一方面,存在通过新线程创建的线程对象。。。构造器。这不是实际执行任何事情的线程。它只是线程机制的一个门面,线程机制实现了与OS/VM交互的标准化API

仅仅创建一个线程实例与创建任何其他java对象基本上没有什么不同。现在还没有发生任何与向OS线程调度程序实际添加线程有关的事情

操作系统端的线程是actua 在私有本机方法start0中创建时,start方法执行一些健全性检查,然后调用start0实际创建操作系统级线程

因此,行动的一般顺序是:

创建并初始化线程对象 还没有什么不寻常的事情发生 在上面的线程对象上调用start 委托本机代码以创建操作系统级线程。操作系统级线程的入口点是java端的thread.run。 在新线程上执行Thread.run,默认执行对创建线程对象时使用的Runnable的运行委托,或者如果没有Runnable,则不执行任何操作

你在哪里读到的?引用一句话可能有助于澄清你的困惑。Start实际上启动这个新线程的并行执行,run只是被调用的方法。此方法运行的位置取决于调用它的线程。Start会从启动的新线程自动调用它。run由Start调用,并且只存在以被重写。如果调用run,则run将由同一线程而不是新线程执行。如果同一线程已完成其作业,则无法再次重新启动该线程。start方法将创建新线程,并将使用新创建的线程在内部调用run方法。您从哪里读到的?引用一句话可能有助于澄清你的困惑。Start实际上启动这个新线程的并行执行,run只是被调用的方法。此方法运行的位置取决于调用它的线程。Start会从启动的新线程自动调用它。run由Start调用,并且只存在以被重写。如果调用run,则run将由同一线程而不是新线程执行。如果同一线程已完成其作业,则无法再次重新启动该线程。start方法将创建新线程,并使用新创建的thread.ok在内部调用run方法。如何在运行中重新执行代码?重新启动线程或使用一个布尔值控制执行的无限循环?@Alex:一般来说,不要在运行时重新执行代码。线程应该一直运行,直到其工作完成,然后线程就完成了它的任务。您认为需要重新运行它的用例是什么?start方法会使线程进入就绪状态。问题是我有一个相对较难的任务需要频繁执行,所以我将它移动到另一个线程。我怀疑人们每次需要执行相同的任务时都会创建一个新线程。还是他们?对于这样的问题,一定有一些好的做法。现在很清楚了。此外,本教程也很方便。非常感谢。可以如何在运行中重新执行代码?重新启动线程或使用一个布尔值控制执行的无限循环?@Alex:一般来说,不要在运行时重新执行代码。线程应该一直运行,直到其工作完成,然后线程就完成了它的任务。您认为需要重新运行它的用例是什么?start方法会使线程进入就绪状态。问题是我有一个相对较难的任务需要频繁执行,所以我将它移动到另一个线程。我怀疑人们每次需要执行相同的任务时都会创建一个新线程。还是他们?对于这样的问题,一定有一些好的做法。现在很清楚了。此外,本教程也很方便。非常感谢。你刚才说Threadstart是错的。因为start方法不创建线程。它使线程进入就绪状态。@Win.Ubuntu更新了我的答案。谢谢你纠正我。说“开始”和“运行”之间有区别是误导。它们都只是方法。它们的调用方式与任何其他方法的调用方式相同。他们都只是按照他们的代码所说的去做。对于Thread.start,它的代码使它创建并启动一个新线程。但是跑步做什么呢?别问我!问问写它的人!Thread.start是库为代码调用以启动新线程提供的方法。Whatever.run是您为库提供的在新线程中调用的方法。@Win.ubuntu为什么您认为thread.start不创建新线程?如果您正在实现Thread类,那么您的实现将在何时创建新线程,为什么?@jameslarge它不会创建新线程。但它创建了一个新的执行线程。试试这个:Thread-Thread=new-Thread->{for;;System.out.printlnhhello…!;};线程=null;thread.start;//线程=null;你刚才说Threadstart是错的。因为start方法不创建线程。它使线程进入就绪状态。@Win.Ubuntu更新了我的答案。谢谢你纠正我。说“开始”和“运行”之间有区别是误导。它们都只是方法。它们的调用方式与任何其他方法的调用方式相同。他们都只是按照他们的代码所说的去做。对于Thread.start,它的代码使它创建并启动一个新线程。但是跑步做什么呢?别问我!问问写它的人!Th
read.start是库为代码调用以启动新线程提供的方法。Whatever.run是您为库提供的在新线程中调用的方法。@Win.ubuntu为什么您认为thread.start不创建新线程?如果您正在实现Thread类,那么您的实现将在何时创建新线程,为什么?@jameslarge它不会创建新线程。但它创建了一个新的执行线程。试试这个:Thread-Thread=new-Thread->{for;;System.out.printlnhhello…!;};线程=null;thread.start;//线程=null;