繁体   English   中英

我想随时停止线程

[英]Stop thread anytime i want

我有一个方法,应该中断一个线程,但事实并非如此。 是否需要一直检查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 次操作,我将 boolean 变量“终止”添加到它现在工作的代码中,我只是想找到一个更好的解决方案:(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();
}
while(somethingistrue !Thread.currentThread().isInterrupted()){
  //do lot of stuff here for long time
}

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

优雅的解决方案是修改您的 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.currentThread().isInterrupted() 如果你想立即响应你的 Thread.interrupt()
  • 您可以删除 if(terminated) return; 或者将其替换为 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);
        }

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

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

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

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

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

“很多东西”在做什么?

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM