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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1881714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:30:29  来源:igfitidea点击:

How to start/stop/restart a thread in Java?

javamultithreading

提问by Shaitan00

I am having a real hard time finding a way to start, stop, and restart a thread in Java.

我真的很难找到一种在 Java 中启动、停止和重新启动线程的方法。

Specifically, I have a class Task(currently implements Runnable) in a file Task.java. My main application needs to be able to START this task on a thread, STOP (kill) the thread when it needs to, and sometimes KILL & RESTART the thread...

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

My first attempt was with ExecutorServicebut I can't seem to find a way for it restart a task. When I use .shutdownnow()any future call to .execute()fails because the ExecutorServiceis "shutdown"...

我的第一次尝试是使用,ExecutorService但我似乎找不到重新启动任务的方法。当我使用.shutdownnow()任何未来的调用.execute()失败时,因为ExecutorService是“关闭”......

So, how could I accomplish this?

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

采纳答案by Taylor Leese

Once a thread stops you cannot restart it. However, there is nothing stopping you from creating and starting a new thread.

一旦线程停止,您将无法重新启动它。但是,没有什么可以阻止您创建和启动新线程。

Option 1:Create a new thread rather than trying to restart.

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

Option 2:Instead of letting the thread stop, have it wait and then when it receives notification you can allow it to do work again. This way the thread never stops and will never need to be restarted.

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

Edit based on comment:

根据评论编辑:

To "kill" the thread you can do something like the following.

要“杀死”线程,您可以执行以下操作。

yourThread.setIsTerminating(true); // tell the thread to stop
yourThread.join(); // wait for the thread to stop

回答by Uri

There's a difference between pausing a thread and stopping/killing it. If stopping for you mean killing the thread, then a restart simply means creating a new thread and launching.

暂停线程和停止/杀死它是有区别的。如果为您停止意味着杀死线程,那么重新启动仅意味着创建一个新线程并启动。

There are methods for killing threads from a different thread (e.g., your spawner), but they are unsafe in general. It might be safer if your thread constantly checks some flag to see if it should continue (I assume there is some loop in your thread), and have the external "controller" change the state of that flag.

有一些方法可以杀死来自不同线程(例如,您的 spawner)的线程,但它们通常是不安全的。如果您的线程不断检查某个标志以查看它是否应该继续(我假设您的线程中有一些循环),并让外部“控制器”更改该标志的状态,则可能会更安全。

You can see a little more in: http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

您可以在以下位置看到更多信息:http: //java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

May I ask why you want to kill the thread and restart it? Why not just have it wait until its services are needed again? Java has synchronization mechanisms exactly for that purpose. The thread will be sleeping until the controller notifies it to continue executing.

请问你为什么要杀死线程并重新启动它?为什么不让它等到再次需要它的服务?Java 具有完全用于此目的的同步机制。线程将处于休眠状态,直到控制器通知它继续执行。

回答by Gennadiy

If your task is performing some kind of action in a loop there is a way to pause/restart processing, but I think it would have to be outside what the Thread API currently offers. If its a single shot process I am not aware of any way to suspend/restart without running into API that has been deprecated or is no longer allowed.

如果您的任务在循环中执行某种操作,则有一种方法可以暂停/重新启动处理,但我认为它必须超出 Thread API 当前提供的范围。如果它是单次处理过程,我不知道有什么方法可以在不运行已弃用或不再允许的 API 的情况下暂停/重新启动。

As for looped processes, the easiest way I could think of is that the code that spawns the Task instantiates a ReentrantLock and passes it to the task, as well as keeping a reference itself. Every time the Task enters its loop it attempts a lock on the ReentrantLock instance and when the loop completes it should unlock. You may want to encapsulate all this try/finally, making sure you let go of the lock at the end of the loop, even if an exception is thrown.

对于循环进程,我能想到的最简单的方法是生成任务的代码实例化一个 ReentrantLock 并将其传递给任务,同时保持引用本身。每次任务进入其循环时,它都会尝试锁定 ReentrantLock 实例,当循环完成时,它应该解锁。您可能希望封装所有这些 try/finally,确保在循环结束时释放锁,即使抛出异常也是如此。

If you want to pause the task simply attempt a lock from the main code (since you kept a reference handy). What this will do is wait for the loop to complete and not let it start another iteration (since the main thread is holding a lock). To restart the thread simply unlock from the main code, this will allow the task to resume its loops.

如果您想暂停任务,只需尝试从主代码中锁定(因为您保留了一个方便的参考)。这将做的是等待循环完成而不是让它开始另一个迭代(因为主线程持有锁)。要重新启动线程,只需从主代码解锁,这将允许任务恢复其循环。

To permanently stop the thread I would use the normal API or leave a flag in the Task and a setter for the flag (something like stopImmediately). When the loop encountered a true value for this flag it stops processing and completes the run method.

要永久停止线程,我将使用普通 API 或在任务中留下一个标志和一个标志的设置器(类似于 stopImmediately)。当循环遇到此标志的真值时,它会停止处理并完成 run 方法。

回答by T.J. Crowder

Review java.lang.Thread.

回顾java.lang.Thread

To start or restart (once a thread is stopped, you can't restart that same thread, but it doesn't matter; just create a new Threadinstance):

启动或重新启动(一旦一个线程停止,你就不能重新启动同一个线程,但这没有关系;只需创建一个新Thread实例):

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

// Start a thread and run your Runnable
Thread t = new Thread(task);

To stop it, have a method on your Taskinstance that sets a flag to tell the runmethod to exit; returning from runexits the thread. If your calling code needs to know the thread really has stopped before it returns, you can use join:

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

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

// Wait for it to do so
t.join();

Regarding restarting: Even though a Threadcan't be restarted, you can reuse your Runnableinstance with a new thread if it has state and such you want to keep; that comes to the same thing. Just make sure your Runnableis designed to allow multiple calls to run.

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

回答by JasCav

As stated by Taylor L, you can't just "stop" a thread (by calling a simple method) due to the fact that it could leave your system in an unstable state as the external calling thread may not know what is going on inside your thread.

正如 Taylor L 所说,您不能只是“停止”一个线程(通过调用一个简单的方法),因为它可能会使您的系统处于不稳定状态,因为外部调用线程可能不知道内部发生了什么你的线程。

With this said, the best way to "stop" a thread is to have the thread keep an eye on itself and to have it know and understand when it should stop.

话虽如此,“停止”线程的最佳方法是让线程关注自身并让它知道并理解何时应该停止。

回答by ChadNC

You can't restart a thread so your best option is to save the current state of the object at the time the thread was stopped and when operations need to continue on that object you can recreate that object using the saved and then start the new thread.

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

These two articles Swing Workerand Concurrencymay help you determine the best solution for your problem.

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

回答by Matt Crinklaw-Vogt

It is impossible to terminate a thread unless the code running in that thread checks for and allows termination.

除非在该线程中运行的代码检查并允许终止,否则不可能终止线程。

You said: "Sadly I must kill/restart it ... I don't have complete control over the contents of the thread and for my situation it requires a restart"

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

If the contents of the thread does not allow for termination of its exectuion then you can not terminate that thread.

如果线程的内容不允许终止其执行,则您不能终止该线程。

In your post you said: "My first attempt was with ExecutorService but I can't seem to find a way for it restart a task. When I use .shutdownnow()..."

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

If you look at the source of "shutdownnow" it just runs through and interrupts the currently running threads. This will not stop their execution unless the code in those threads checks to see if it has been ineterrupted and, if so, stops execution itself. So shutdownnow is probably not doing what you think.

如果您查看“shutdownnow”的来源,它只会运行并中断当前正在运行的线程。这不会停止它们的执行,除非这些线程中的代码检查它是否已被中断,如果是,则停止执行本身。所以 shutdownnow 可能没有按照你的想法去做。

Let me illustrate what I mean when I say that the contents of the thread must allow for that thread to be terminated:

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

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

That thread will continue to run forever, even though shutdownnow was called, because it never checks to see if it has been terminated or not. This thread, however, will shut down:

即使调用了shutdownnow,该线程也将永远运行,因为它从不检查它是否已终止。但是,此线程将关闭:

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

Since this thread checks to see whether or not it has been interrupted / shut down / terminated.

由于此线程会检查它是否已被中断/关闭/终止。

So if you want a thread that you can shut down, you need to make sure it checks to see if it has been interrupted. If you want a thread that you can "shut down" and "restart" you can make a runnable that can take new tasks as was mentioned before.

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

Why can you not shut down a running thread? Well I actually lied, you can call "yourThread.stop()" but why is this a bad idea? The thread could be in a synchronized (or other critical section, but we will limit ourselves to setions guarded by the syncrhonized key word here) section of code when you stop it. synch blocks are supposed to be executed in their entirity and only by one thread before being accessed by some other thread. If you stop a thread in the middle of a synch block, the protection put into place by the synch block is invalidated and your program will get into an unknown state. Developers make put stuff in synch blocks to keep things in synch, if you use threadInstance.stop() you destroy the meaning of synchronize, what the developer of that code was trying to accomplish and how the developer of that code expected his synchronized blocks to behave.

为什么不能关闭正在运行的线程?好吧,我实际上撒了谎,您可以调用“yourThread.stop()”,但为什么这是个坏主意?当您停止线程时,该线程可能位于代码的同步(或其他临界区,但我们将限制在由同步关键字保护的设置)部分。同步块应该在它们的整体中执行,并且在被其他线程访问之前只能由一个线程执行。如果您在同步块中间停止线程,则同步块设置的保护将失效,您的程序将进入未知状态。开发者把东西放在同步块中以保持同步,如果使用 threadInstance.stop() 就破坏了同步的意义,

回答by mmirwaldt

I completely disagree with the claim "you cannot 'stop' a thread". It is a shortsighted view on a thorny issue. Why?

我完全不同意“你不能‘停止’一个线程”的说法。这是对棘手问题的短视。为什么?

Checking regularly the interrupted-flag is actually nothing else than another form of busy waiting with the difficult decision of "when to check the flag and how often". Can be very ugly or impossible to answer. The class thread also has the method "stop(Throwable throwable)" which is unfortunately deprecated what I deeply disapprove. Given the method run() with its body in a try-catch-finally-statement: Why is it OK that any statement (from inside the body) may throw any checked or unchecked exception while an invocation of stop(new MyRuntimeException()) from outside may not? Is it really so unexpected from outside? Then what about rethrown unexpected RuntimeExceptions which are rarely caught as they are often unknown? At the end, the catch-clauses have to deal with the exception - whether it is from inside or from outside. And the finally-block can tidy up. I hope, people think about that design issue again.

定期检查中断标志实际上是另一种形式的忙等待,需要艰难地决定“何时检查标志以及多久检查一次”。可能非常难看或无法回答。类线程也有方法“stop(Throwable throwable)”,不幸的是,它弃用了我非常不赞成的方法。给定方法 run() 及其主体在 try-catch-finally-statement 中:为什么在调用 stop(new MyRuntimeException()) 时任何语句(来自主体内部)都可以抛出任何已检查或未检查的异常从外面可能不会?真的有这么出乎外界的意料吗?那么如何重新抛出意外的 RuntimeExceptions,因为它们通常是未知的,所以很少被捕获?最后,catch 子句必须处理异常——无论是来自内部还是外部。最后块可以整理。我希望,人们再次考虑那个设计问题。

I think a thread should be able to die (by terminating on its own) or to be killed (immediately terminated with an exception).

我认为一个线程应该能够死亡(通过自己终止)或被杀死(立即因异常而终止)。

回答by Saravanan Thangavel

Sometimes if a Threadwas started and it loaded a downside dynamic class which is processing with lots of Thread/currentThreadsleep while ignoring interrupted Exceptioncatch(es), one interrupt might not be enough to completely exit execution.

有时,如果 aThread启动并加载了一个不利的动态类,该类正在处理大量Thread/ currentThreadsleep 而忽略中断的Exceptioncatch(es),一个中断可能不足以完全退出执行。

In that case, we can supply these loop-based interrupts:

在这种情况下,我们可以提供这些基于循环的中断:

while(th.isAlive()){
    log.trace("Still processing Internally; Sending Interrupt;");
    th.interrupt();
    try {
        Thread.currentThread().sleep(100);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

回答by Sukirti Dash

You can start a thread like:

    Thread thread=new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //Do you task
                    }catch (Exception ex){
                        ex.printStackTrace();}
                }
            });
thread.start();

To stop a Thread:

   thread.join();//it will kill you thread

   //if you want to know whether your thread is alive or dead you can use
System.out.println("Thread is "+thread.isAlive());

Its advisable to create a new thread rather than restarting it.

建议创建一个新线程而不是重新启动它。