【问题标题】:How to stop a thread created by implementing runnable interface?如何停止通过实现可运行接口创建的线程?
【发布时间】:2023-03-14 14:52:01
【问题描述】:

我通过实现可运行接口创建了类,然后在我的项目的其他一些类中创建了许多线程(近 10 个)。
如何停止其中一些线程?

【问题讨论】:

    标签: java multithreading thread-safety


    【解决方案1】:

    最简单的方式是interrupt()它,这将导致Thread.currentThread().isInterrupted()返回true,并且在线程为的某些情况下还可能抛出InterruptedException 等待,例如Thread.sleep()otherThread.join()object.wait()

    run() 方法中,您需要捕获该异常和/或定期检查 Thread.currentThread().isInterrupted() 值并执行某些操作(例如,突破)。

    注意:虽然Thread.interrupted() 看起来与isInterrupted() 相同,但它有一个讨厌的副作用:调用interrupted() 清除 interrupted 标志,而调用isInterrupted() 则不会。

    其他非中断方法涉及使用正在运行的线程监控的“停止”(volatile) 标志。

    【讨论】:

    • 我的线程中没有while,但有时我仍然需要在它处理run 方法中的所有行之前停止它
    【解决方案2】:

    如何停止通过实现可运行接口创建的线程?

    有很多方法可以停止线程,但它们都需要特定的代码来完成。停止线程的典型方法是设置一个volatile boolean shutdown 字段,线程会经常检查该字段:

      // set this to true to stop the thread
      volatile boolean shutdown = false;
      ...
      public void run() {
          while (!shutdown) {
              // continue processing
          }
      }
    

    您还可以中断导致sleep()wait() 和其他一些方法抛出InterruptedException 的线程。您还应该使用以下内容测试线程中断标志:

      public void run() {
          while (!Thread.currentThread().isInterrupted()) {
              // continue processing
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  // good practice
                  Thread.currentThread().interrupt();
                  return;
              }
          }
      }
    

    请注意,使用interrupt() 中断线程不一定会导致它立即抛出异常。只有当你在一个可中断的方法中时,InterruptedException 才会被抛出。

    如果您想在实现Runnable 的类中添加shutdown() 方法,您应该定义自己的类,例如:

    public class MyRunnable implements Runnable {
        private volatile boolean shutdown;
        public void run() {
            while (!shutdown) {
                ...
            }
        }
        public void shutdown() {
            shutdown = true;
        }
    }
    

    【讨论】:

    • 在我的班级中,我编写了一个将标志(在您的示例中为关闭)设置为 true 的方法。但我无法从需要停止线程的其他班级访问此方法。跨度>
    • 是的,您需要以某种方式公开它。我通常会做类似public class MyClass implements Runnable { volatile boolean shutdown; public void run() { if (! shutdown) { ... } } } 的事情。您可以添加一个设置关闭标志的shutdown() 方法。然后你会做new Thread(new MyClass()).start(); 来运行它。
    • 我的线程中没有while,但有时我仍然需要在它处理run 方法中的所有行之前停止它
    • 然后你可以使用if@user25。如果您需要更多帮助,我会花时间问一个完整的问题。
    【解决方案3】:

    停止使用Thread.stop() 中途的线程不是一个好习惯。更合适的方法是让线程以编程方式返回。让 Runnable 对象在run() 方法中使用共享变量。每当您希望线程停止时,将该变量用作标志。

    编辑:示例代码

    class MyThread implements Runnable{
        
        private Boolean stop = false;
        
        public void run(){
            
            while(!stop){
                
                //some business logic
            }
        }
        public Boolean getStop() {
            return stop;
        }
    
        public void setStop(Boolean stop) {
            this.stop = stop;
        }       
    }
    
    public class TestStop {
        
        public static void main(String[] args){
            
            MyThread myThread = new MyThread();
            Thread th = new Thread(myThread);
            th.start();
            
            //Some logic goes there to decide whether to 
            //stop the thread or not. 
            
            //This will compell the thread to stop
            myThread.setStop(true);
        }
    }
    

    【讨论】:

    • 在我的班级中,我编写了一个将标志设置为 false 的方法。但我无法从需要停止线程的其他班级访问此方法。
    • 假设创建线程的类负责停止它,则应在此类中维护对 Runnable 实例的引用,并使用此引用调用设置标志的方法。
    • 如果你不介意,你可以举个例子更清楚一点
    • 你应该让你的stop变量可变。
    • 如果我想在 some bussiness logic 中间取消怎么办,这不会让它运行“整个业务逻辑”吗?因为在 while 循环的下一次迭代中正在检查标志。
    【解决方案4】:

    如果你使用ThreadPoolExecutor,并且你使用submit()方法,它会给你一个Future。您可以在返回的 Future 上调用 cancel() 来停止您的 Runnable 任务。

    【讨论】:

    • cancel 尝试取消执行,但不保证。
    【解决方案5】:

    不建议在中途停止(杀死)线程。 API 实际上已被弃用。

    但是,您可以在此处获取更多详细信息,包括解决方法:How do you kill a thread in Java?

    【讨论】:

      【解决方案6】:

      Thread.currentThread().isInterrupted() 运行良好。但是这个 代码只是暂停计时器。

      此代码是停止并重置线程计时器。 h1 是处理程序名称。 此代码添加在您的按钮单击侦听器中。 w_h =分钟 w_m =毫秒 i=计数器

       i=0;
                  w_h = 0;
                  w_m = 0;
      
      
                  textView.setText(String.format("%02d", w_h) + ":" + String.format("%02d", w_m));
                              hl.removeCallbacksAndMessages(null);
                              Thread.currentThread().isInterrupted();
      
      
                              }
      
      
                          });
      
      
                      }`
      

      【讨论】:

        猜你喜欢
        • 2018-03-07
        • 1970-01-01
        • 2013-06-11
        • 1970-01-01
        • 2021-02-04
        • 2019-10-08
        • 1970-01-01
        • 1970-01-01
        • 2014-07-15
        相关资源
        最近更新 更多