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);
                        }
                    }
                }
            }
        }

和全旋转方法:

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();
}
4

5 回答 5

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

不必为阻塞 IO 工作。使用肮脏的技巧:覆盖 Thread.interrupt() 关闭 IO 对象,导致 IOException,如果处理得当,可能会结束线程运行方法。

于 2012-04-09T11:43:55.270 回答
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。如果没有所有这些 if(terminated) ,代码也会更干净。
  • 使用 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);
        }
于 2012-04-09T13:08:04.170 回答
0

当一个线程正在运行时(消耗 CPU 周期),那么默认情况下它不会(自动)响应Thread.interrupt()。您将不得不编写代码来明确地执行此操作。

//do lot of stuff here for long time分成 2 个或更多步骤,并在这些步骤之间插入检查Thread.currentThread().isInterrupted()- if true - break out ,否则继续。这是实现您想要的唯一安全方法。

这取决于长期运行的东西是什么,您必须设计步骤并决定何时最好检查中断和突破。

于 2012-04-09T11:48:45.557 回答
0

中断线程的唯一方法是让它自行退出。由于死锁的可能性,Java 甚至没有实现直接中断。因此,您的线程代码必须如下所示:

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

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

于 2012-04-09T11:39:12.627 回答
0

唯一可以可靠地阻止一个线程从另一个线程执行的是操作系统。所以,选择并不多:

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

“很多东西”在做什么?

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

3)使用单独的进程来运行“东西”。这显然可以正常工作,但通常涉及缓慢而痛苦的进程间通信来传递数据和返回结果。

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

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

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

于 2012-04-09T11:40:45.377 回答