2012-04-09 52 views
1

我有一个方法,应该中断一个线程,但它不是。我是否需要始终检查while方法中断的线程来停止线程?我怎样才能随时终止线程?随时停止线程我想要

solverTh = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while(somethingistrue){ 
       //do lot of stuff here for long time 
      } 
     } 
    }); 
    solverTh.start(); 
} 

public void terminate(){ 
    if(solverTh != null){ 
     solverTh.interrupt(); 
    } 
} 

没关系比我认为“很多东西”是不相关的,但我会发布它比。它使openGL操作,我现在的代码添加布尔变量“终止”,我只是想找到一个更好的解决方案: (glc是一个GLCanvas,和rotmultiplecube方法旋转3个对象) 反正我解决了现在的问题,谢谢你的答案。

  terminated = false; 
      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      int colorToBeSolved = Statics.RED_BLUE_TABLE[stateToBeSolved]; 
      System.out.println(stateToBeSolved + "," + colorToBeSolved); 
      if(entities[0].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.FIRST_ROW, Statics.DOWN); 
      } 
      if(entities[1].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.SECOND_COL, Statics.RIGHT); 
      } 
      if(entities[2].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.THIRD_COL, Statics.RIGHT); 
      } 
      if(entities[3].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.SECOND_ROW, Statics.DOWN); 
      } 
      if(entities[6].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.THIDR_ROW, Statics.DOWN); 
      } 

      for(int i = 0; i < 9; ++i){ 
       int col = i % 3; 
       int row = 3 + i/3; 
       while(entities[i].getState() != stateToBeSolved){ 
        for(int j = 0;j < 2; ++j){ 
         if(entities[i].getState() != stateToBeSolved){ 
          if(terminated) return; 
          fullRotate(col, Statics.LEFT); 
          if(terminated) return; 
          fullRotate(row, Statics.UP); 
          if(terminated) return; 
          fullRotate(col, Statics.RIGHT); 
          if(terminated) return; 
          fullRotate(row, Statics.DOWN); 
         } 
        } 
        for(int j = 0;j < 2; ++j){ 
         if(entities[i].getState() != stateToBeSolved){ 
          if(terminated) return; 
          fullRotate(col, Statics.RIGHT); 
          if(terminated) return; 
          fullRotate(row, Statics.UP); 
          if(terminated) return; 
          fullRotate(col, Statics.LEFT); 
          if(terminated) return; 
          fullRotate(row, Statics.DOWN); 
         } 
        } 
       } 
      } 
     } 

和fullrotate方法:

private void fullRotate(int selectionIndex, int direction){ 
    for(int i = 0; i < 9; ++i){ 
     glc.rotMultipleCubeSlow(selectionIndex, direction); 
     try { 
      Thread.sleep(20); 
     } catch (InterruptedException ex) { 
      terminate(); 
     } 
    } 
    glc.setMovesText(selectionIndex, direction);   
    glc.setMultipleStateAndColorsByTable(selectionIndex, direction); 
    glc.isEntitiesRight(); 
} 
+0

1)*“我怎样才能刚刚终止线程在任何时候?“*你认为你可以实现Java的制造商说他们不能(至少,不安全)? 2)'//在很长一段时间里做很多事情'代码说话比语言更响亮。为了更快地获得更好的帮助,请发布[SSCCE](http://sscce.org/)。 – 2012-04-09 11:10:22

+0

你检查:http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html – anuragsn7 2012-04-09 11:28:55

回答

1

优雅的解决方案是修改您的fullRotate()方法抛出InterruptedException。

private void fullRotate(int selectionIndex, int direction) 
     throws InterruptedException{ 
    for(int i = 0; i < 9; ++i){ 
     glc.rotMultipleCubeSlow(selectionIndex, direction); 
     Thread.yield(); 
    } 
    glc.setMovesText(selectionIndex, direction);   
    glc.setMultipleStateAndColorsByTable(selectionIndex, direction); 
    glc.isEntitiesRight(); 
} 
  • 当你调用了Thread.interrupt()你造成任何InterruptedException的那把它的方法被调用时,你的情况Thread.sleep()方法或Thread.yield()。这意味着最好的方法是使用它来实际中断计算。如果你想要立即回应你的Thread.interrupt()
  • 你仍然需要检查Thread.currentThread()。isInterrupted()如果(终止)返回;或者用Thread.currentThread()。isInterrupted()检查来代替它。删除会很好,因为来自fullRotate()的Thread.sleep(20)/Thread.yield()会抛出InterruptedException。如果(终止)所有的地方,也没有所有这些代码将更清洁。
  • 使用Thread.yield(),而不是用于了Thread.sleep(20)。显然你不想睡觉,因为你把20毫米。 20 milis非常接近上下文切换时间量。线程将会更多或更少地睡眠。你不希望它没有任何理由睡得更多,所以使用yield()。

你线程的run()则变为:

solverTh = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     while(somethingistrue && 
       !Thread.currentThread().isInterrupted()) { 
      try { 
       //do lot of stuff here for long time 
      } catch (InterruptedException ex) { 
       // handle stop processing 
      } 
     } 
    } 
}); 
solverTh.start(); 

你也必须从下面取出的尝试捕捉:

 try { 
      Thread.sleep(2000); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex); 
     } 
+0

确保您重置捕获块中的中断状态,否则while循环将继续运行。 – 2012-04-09 18:23:12

+0

这听起来好多了,非常感谢!我会尝试 – 2012-04-10 11:10:43

+0

@FerencDajka请不要忘记接受答案:) – hidralisk 2012-04-10 17:31:21

0

中断线程的唯一方法是让它退出本身。由于死锁的可能性,Strightforward中断甚至没有在Java中实现。所以,你的线程代码必须看起来像:

solverTh = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     while(somethingistrue) 
      // Do a little stuff here 
     } 
    } 
}); 
solverTh.start(); 

而且somethingistrue是一种信号的线程中断。

+0

如果“小东西”是一个单CPU密集型任务?在完成之前,条件不会被查看 – mbatchkarov 2012-04-09 11:51:15

+0

是的,这样的任务总是很痛苦。但无论如何,可以找到一个解决方法。例如,如果这个CPU密集型任务是单独的进程,则线程可以在每个时间间隔检查退出条件,并在需要时将其终止(可轻松处理进程)。 – 2012-04-09 12:06:33

0

唯一能够可靠地停止从另一个线程执行的操作是操作系统。所以,没有太多的选择:

1)发信号线程停止自己。这个方案有点取决于线程在做什么。如果它在另一个处理器上运行,或者阻塞呼叫,则无法解锁,(请注意,很多阻止呼叫可以被提前返回),但可能会出现问题。

什么是“很多东西”在做什么?

2)使用OS调用来终止线程。这可能是一个可行的选择,取决于线程的功能。如果在重要资源上持有公共锁的情况下(例如,它位于malloc()的中间并锁定了内存管理器),则有可能终止该线程,那么您可能会遇到麻烦。你必须确定线程正在做什么来以这种方式安全地中止它。

3)使用一个单独的过程来运行'东西'。这显然可以正常工作,但通常需要缓慢且痛苦的进程间通信来传递数据并返回结果。

4)设计应用程序,以便它不需要终止线程。有些应用程序永远不需要终止除应用程序关闭以外的任何线程,所以没有任何问题 - 操作系统可以阻止任何事情。在应用程序运行期间线程必须“停止”并且正在运行冗长的CPU密集型操作或在很长且可能不确定的时间段内被阻塞的情况下,通过将线程优先级设置为最小/空闲并仅仅“孤立”让它最终死掉是另一种常见的方法。

最糟糕的情况是线程长时间运行很多东西,它使用内存管理器或其他公共锁,可能在一个库中,你不知道它在做什么,不能挂钩并以“孤立”的方式读写数据意味着另一个线程无法启动以使用数据。那时你真的很郁闷,你可能不得不终止应用程序并重新启动。这是最好的,以避免线程可以进入这种状态的设计:)

5)忘记一个 - 如果线程正在使用您可以获取的数据,设置为NULL,0,MaxInt或其他一些像bodge可能会导致在运行很长的东西的线程中引发异常。当执行冒出很长的东西时,线程可以检查异常处理程序中的中断状态,并在设置时退出。

2
while(somethingistrue !Thread.currentThread().isInterrupted()){ 
    //do lot of stuff here for long time 
} 

不必阻止IO工作。使用肮脏的技巧:重写Thread.interrupt()关闭IO对象,导致IOException,如果处理正确可能会结束线程运行方法。

+0

+1是 - 搞鬼:)另一种是迫使一个文件夹观察家API写一个临时文件到监视文件夹返回之一。可以通过打开本地客户端连接或发送空的UDP消息来使UDP套接字读取/ TCP接受返回。 – 2012-04-09 12:27:26

+0

该死的,这对第三方库来说是一个非常方便的诡计!非常感谢! – parasietje 2012-04-10 13:30:04

0

当一个线程正在运行(消耗的CPU周期),那么就不会由默认(自动地)到Thread.interrupt()响应。你将不得不编写代码来明确地做到这一点。

//do lot of stuff here for long time分解为2个或更多步骤,并在这些步骤之间插入检查Thread.currentThread().isInterrupted() - 如果为true,则发生爆发,否则继续。这只是实现你想要的安全方式。

这取决于长时间运行的东西是什么,你就要来设计的步骤,并决定它最好的时候,检查中断和突破。