停止runnable对象是否等同于停止线程?

时间:2017-04-27 20:31:22

标签: java multithreading

鉴于此代码:

public class Game implements Runnable {
  private volatile boolean stop;

  public Game() {
    ...
  }

  public void run() {
    while(!stop) {
      // play game
    }
  }

  public void stopGame() {
    stop = true;
  }
}

public class Main {

  public static void main(String[] args){
    Game g = new Game(); // Game class implements Runnable
    Thread t = new Thread(g);
    t.start();
    // do the two method calls below effectively do the same thing?
    t.interrupt();
    g.stopGame(); 
  }

}

stopGame()是否像使用中断或java.lang.Thread方法杀死线程一样有效地杀死线程? (我不太熟悉你如何使用Thread方法杀死一个线程。)

此外,在stopGame()是杀死线程的最佳方法的情况下,如果他们只能访问Thread实例(如下所示),是否可以调用它:

public static void Main(String[] args){
  List<Thread> threads = new ArrayList<Thread>();
  threads.add(new Thread(new Game()));
  // can you access the Game instance given the Thread instance 
  // or do you need to hold onto the reference of the Game instance?
  threads.get(0).stopGame(); // for example, this won't work.
}

2 个答案:

答案 0 :(得分:4)

  

stopGame()是否像使用中断或java.lang.Thread方法一样有效地停止线程? (我不太熟悉你如何使用Thread方法杀死一个线程。)

停止线程的最佳方法是从run()方法返回。

你的stopGame()调用会在下一次循环中导致这种情况。但是如果该循环包括阻塞调用,那么下一次传递可能会在延迟之后发生 - 或者永远不会发生。

不推荐使用杀死线程的方法,因为它们本质上是不安全的。

Thread.interrupt()无法保证停止任意线程。它唤醒了一些阻塞调用。在捕获InterruptedException时,Runnable停止是常见的 - 但不是通用的。来自Java tutorial on interrupts

  

中断是一个线程的指示,它应该停止它正在做的事情并做其他事情。由程序员决定线程如何响应中断,但线程终止是很常见的。

一种方法是两者设置用户定义的标志并调用Thread.interrupt()。这将中断任何阻塞调用,即使Runnable调用的代码捕获了InterruptedException或清除了中断状态标志,也会工作。

  

此外,在stopGame()是杀死线程的最佳方法的情况下,如果他们只能访问Thread实例(如下所示),是否可以调用它:

您可以将Thread子类化为持有游戏并在子类中提供一种方法来停止游戏。但是,单独跟踪Runnable实例通常更容易。

答案 1 :(得分:0)

“杀死”线程是一种异常情况。

interrupt()方法可以完成这项工作,但在这种情况下,您不需要在run()方法的while条件下使用布尔标志。
这个:

  public void run() {
    while(!stop) {
      // play game
    }
  }

可能是:

  public void run() {            
      while (!Thread.currentThread().isInterrupted()) {
         // play game
      }                
  }

但就个人而言,我发现这是一种积极的方式来阻止线程,因为被中断线程的任何阻塞调用都会被唤醒。
当您处于正常退出情况时,您可能会被迫处理这种过早退出,这可能会造成不一致。
 使用boolean标志可以让线程代码负责完成工作,因为它认为它应该不会强制存在阻塞调用。

这并不意味着永远不应该处理InterruptedException,但我认为对于正常情况(退出用户请求),根据需要使代码更复杂是没有意义的。 BR />

  

stopGame()是否像使用类似的东西一样有效地杀死线程   中断,还是java.lang.Thread方法来杀死线程?

结束线程的合适方法是允许它终止执行:即方法的run()完成执行。

使用boolean条件与while正如您所做的那样很好:

public void run() {
    while(!stop) {
      // play game
    }
  }
  

另外,在stopGame()是杀死线程的最佳方法的情况下,是   有任何调用它,如果他们只有访问Thread实例   如下所示:

你可以这样做:

  Game game = new Game(); 
  game.start();
  ...
  game.stopGame();