随时随地停止线程

时间:2012-04-09 11:07:02

标签: java multithreading interrupt terminate

我有一个方法,它应该打断一个线程,但事实并非如此。我是否需要始终检查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();
}

5 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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 catch:

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

答案 2 :(得分:0)

中断线程的唯一方法是让它自己退出。由于死锁的可能性,甚至在Java中都没有实现严格的中断。所以你的线程代码必须如下:

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

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

答案 3 :(得分:0)

唯一能够可靠地阻止一个线程从另一个线程执行的是OS。所以,选择的选择不多:

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

'很多东西'做什么?

2)使用OS调用终止线程。这可能是一个可行的选择,具体取决于线程的作用。如果在重要资源上持有公共锁定时有任何终止线程的可能性(例如,它位于malloc()的中间并且内存管理器被锁定),那么您可能会遇到麻烦。你必须确定通过这种方式安全地中止它所采取的线程。

3)使用单独的流程来运行'stuff'。这显然可行,但通常涉及缓慢而痛苦的进程间通信以传递数据并返回结果。

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

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

5)忘记一个 - 如果线程正在使用你可以获得的数据,将某些东西设置为NULL,0,MaxInt或其他类似bodge会导致在运行long stuff的线程中引发异常。当执行出现长事件时,线程可以检查异常处理程序中的中断状态,如果设置则退出。

答案 4 :(得分:0)

当线程正在运行(消耗CPU周期)时,默认情况下(自动)不会响应Thread.interrupt()。您必须编写代码才能明确地执行此操作。

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

这取决于长时间运行的东西,你必须设计步骤并决定何时检查中断和突破。