如何在Java中启动/停止/重启线程?

Sha*_*n00 49 java multithreading

我真的很难找到一种方法来启动,停止和重新启动Java中的线程.

具体来说,我在一个文件中有一个类Task(当前实现Runnable)Task.java.我的主应用程序需要能够在一个线程上启动此任务,在需要时停止(终止)该线程,有时需要KILL&RESTART线程......

我的第一次尝试是,ExecutorService但我似乎找不到重启任务的方法.当我使用.shutdownnow()任何未来的电话.execute()失败,因为它ExecutorService是"关机"...

那么,我怎么能做到这一点?

Tay*_*ese 42

线程停止后,您无法重新启动它.但是,没有什么能阻止您创建和启动新线程.

选项1:创建新线程而不是尝试重新启动.

选项2:不要让线程停止,让它等待,然后当它收到通知时,你可以让它再次工作.这样线程永远不会停止,永远不需要重新启动.

根据评论进行编辑:

要"杀死"线程,您可以执行以下操作.

yourThread.setIsTerminating(true); // tell the thread to stop
yourThread.join(); // wait for the thread to stop
Run Code Online (Sandbox Code Playgroud)

  • **在1.6或1.7中的线程**中没有这样的方法setIsTerminating().请澄清你的帖子 - 程序员必须自己设置和检查标志. (15认同)
  • setIsTerminating(true)将是你实现的东西,会告诉thead停止.请参阅上面的评论. (3认同)
  • @ TaylorLeese-这个答案非常有用.能否请您提供有关您提供的选项2的更多信息.看起来大多数讨论是关于第一个选项.能否请您指向一些代码库或网站,在那里我可以找到如何使线程等待并在收到通知时继续工作 (3认同)

T.J*_*der 9

回顾java.lang.Thread.

要启动或重新启动(一旦线程停止,您就无法重新启动相同的线程,但这并不重要;只需创建一个新Thread实例):

// Create your Runnable instance
Task task = new Task(...);

// Start a thread and run your Runnable
Thread t = new Thread(task);
Run Code Online (Sandbox Code Playgroud)

要停止它,请在您的Task实例上设置一个方法,设置一个标志来告诉run方法退出; 从run退出线程返回.如果您的调用代码需要知道线程在返回之前已经停止了,您可以使用join:

// Tell Task to stop
task.setStopFlag(true);

// Wait for it to do so
t.join();
Run Code Online (Sandbox Code Playgroud)

关于重新启动:即使Thread无法重新启动,也可以使用Runnable新线程重用您的实例,如果它具有状态并且您想要保留; 这是相同的事情.只需确保您Runnable的设计允许多次通话run.

  • @ Shaitan00:如果你在讨论'accept`调用时遇到`ServerSocket`阻塞,那么只需要在套接字上调用`setStopFlag`来调用`close`.`accept`调用将通过抛出`SocketException`来解除阻塞.阻止的任何其他东西几乎肯定会有一个类似的退出模式. (2认同)

Mat*_*ogt 9

除非在该线程中运行的代码检查并允许终止,否则无法终止线程.

你说:"可悲的是我必须杀死/重启它......我没有完全控制线程的内容,对于我的情况,它需要重新启动"

如果线程的内容不允许终止其exectuion,那么你就无法终止该线程.

在你的帖子中你说:"我的第一次尝试是使用ExecutorService,但我似乎找不到重启任务的方法.当我使用.shutdownnow()......"

如果查看"shutdownnow"的来源,它只会运行并中断当前运行的线程.这不会停止执行,除非这些线程中的代码检查它是否已被打乱,如果是,则自行停止执行.因此,shutdownnow可能没有按照你的想法行事.

让我说明当我说线程的内容必须允许该线程被终止时我的意思:

myExecutor.execute(new Runnable() {
 public void run() {
  while (true) {
    System.out.println("running");
  }
 }
 });
myExecutor.shutdownnow();
Run Code Online (Sandbox Code Playgroud)

该线程将继续运行,即使调用了shutdownnow,因为它永远不会检查它是否已被终止.但是,该线程将关闭:

myExecutor.execute(new Runnable() {
 public void run() {
  while (!Thread.interrupted()) {
    System.out.println("running");
  }
 }
 });
myExecutor.shutdownnow();
Run Code Online (Sandbox Code Playgroud)

由于该线程检查它是否已被中断/关闭/终止.

因此,如果您想要一个可以关闭的线程,您需要确保它检查它是否已被中断.如果你想要一个可以"关闭"和"重新启动"的线程,你就可以创建一个可以执行前面提到的新任务的runnable.

为什么不能关闭正在运行的线程?好吧,我实际上撒谎,你可以调用"yourThread.stop()",但为什么这是一个坏主意?当你停止它时,该线程可能处于同步(或其他关键部分,但我们将限制在这里由同步关键字保护的部分)部分代码中.synch块应该在它们的整数中执行,并且在被其他一些线程访问之前只能由一个线程执行.如果在同步块中间停止某个线程,则synch块保护的保护将失效,程序将进入未知状态.开发人员将内容置于同步块中以保持同步,如果使用threadInstance.stop(),则会破坏同步的含义,该代码的开发人员试图完成的内容以及该代码的开发人员如何期望他的同步块表现.


Cha*_*dNC 5

您无法重新启动线程,所以最好的选择是在线程停止时保存对象的当前状态,并且当需要继续对该对象进行操作时,可以使用保存的对象重新创建该对象,然后启动新线程。

Swing Worker并发性》这两篇文章可能会帮助您确定问题的最佳解决方案。