【问题标题】:Java thread doesn't stop/interruptJava 线程不会停止/中断
【发布时间】:2013-12-28 18:37:23
【问题描述】:

我正在尝试终止一个线程,但它不会中断或停止。所有这些都是名为 Webots 的软件控制器的一部分。我用它来模拟一个多机器人系统。在每个机器人的控制器中,我启动了一个线程,该线程通过机器人接收器接收消息。该线程必须首先启动,并在模拟结束时终止。

这个线程的run方法如下所示:

public void run() {
    while (true)
    {
        String M = recieveMessage();
        char[] chars = M.toCharArray();
        if(chars[0]==robotName||chars[0]=='0')
            messages.add(M);                                                
     }
}

在主控制器中,我的代码如下所示:

MessageThread MT = new MessageThread(messages, receiver,getName());
MT.start();
for (int i = 0; i < 100; i++)
{
    try
    {
         Thread.sleep(25);  } catch (InterruptedException e) {      e.printStackTrace();    }
    System.out.println(messages.get(messages.size()-1));                
 }
 MT.interrupt();//MT = null;
 System.out.println(MT.interrupted());

我在主控制器中做什么并不重要,所以不要评判它。例如,messages 是一个 ArrayList。它就像一个缓冲区,MT 将消息放入其中,主线程从中读取。我使用它是因为接收器和发射器不同步。

如果我调用了 interrupt() 或 MT = null but interrupted() 它返回 false 并且 MT 继续运行。我的代码有什么问题吗?

我阅读了一些主题,例如:

http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

How do you kill a Thread in Java?

interrupt() doesn't work

Java: How interrupt/stop a thread?

等等,但我找不到任何有用的答案。

编辑

谢谢大家,我已经对我的代码进行了更改。我将此添加到 MessageThread 类:

private volatile boolean isRunning = true;

然后我用while(isRunning)而不是while(true)并添加了

public void kill()
{
    isRunning = false;
}

并调用MT.kill() 而不是MT.interrupt()

它有效,但我无法找出中断()有什么问题。我阅读了@ExtremeCoders 推荐的链接。但是,我仍然很困惑。它说“一个线程必须支持它自己的中断”。 那么我必须覆盖interrupt() 方法吗?我不能调用中断来终止线程吗?

再次感谢。

【问题讨论】:

  • 您认为interrupt 会做什么?你想达到什么目的?
  • 我想在我的主控制器完成时停止 MT 线程。
  • interrupt 不像你想的那样工作。您必须在循环中检查 interrupted 标志并相应地中断。见this链接
  • 那么如何停止 MT 线程呢?我知道 Thread.stop() 有一些问题。在 java 文档中,他们通过将线程设置为 null 来停止线程。我试过了,但还是不行。
  • @Taher 而不是 while(true) 循环使用 while(!Thread.interrupted())

标签: java multithreading


【解决方案1】:

中断线程只是在线程上设置一个标志。如果线程从不检查标志,它将不会响应。通过创建自己的 boolean 成员,您不必要地复制了该功能。

这是您尝试做的一般模式:

@Override
public void run() {
  while(!Thread.interrupted() {
    /* Do something. */
  }
  Thread.currentThread().interrupt();
}

这将允许您按预期拨打MT.interrupt()。这比创建自己的标志和自定义方法来设置它要好:您可以将Runnable 任务与ExecutorService 等高级工具一起使用,并且取消将起作用,因为您使用了标准API;整个ThreadGroup 的中断也是如此。

调用Thread.interrupted()清除线程的中断状态;我们通过调用Thread.currentThread().interrupt()来设置它,再次设置状态以便run()的调用者可以检测到中断状态。然而,这可能并不总是可取的。

【讨论】:

  • 谢谢,正如@ExtremeCoders 所建议的,我使用了while(!Thread.interrupted()) 但MT Thread 并没有停止!!!所以我决定定义自己的标志。
  • @Taher 你把它和打电话给MT.interrupt() 一起用了吗?因为它肯定会起作用;如果没有,你做错了什么。
  • 是的,我做到了,我很惊讶为什么 MT 仍在运行。我用 while(!Thread.interrupted()) 更改了我的 while 循环,并添加了 read.currentThread().interrupt();过了一会儿,我在主线程中调用了 MT.interrupt()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
相关资源
最近更新 更多