简体   繁体   English

我想随时停止线程

[英]Stop thread anytime i want

I have a method, wich supposed to interrupt a thread, but it's not.我有一个方法,应该中断一个线程,但事实并非如此。 Do I need to always check the thread interrupted in the while method to stop the thread?是否需要一直检查while方法中中断的线程来停止线程? How can I just terminate the thread at anytime?我怎样才能随时终止线程?

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

okay than I thought the "lot of stuff" is irrelevant, but I will post it than.好吧,我认为“很多东西”无关紧要,但我会发布它。 It makes openGL operations, I added the boolean variable "terminated" to the code it works now, I just wanted to find a nicer solution: (glc is a GLCanvas, and the rotmultiplecube method rotates 3 objects) Anyways I've solved the problem now, thanks for the answers.它进行了 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);
                        }
                    }
                }
            }
        }

and the fullrotate method:和全旋转方法:

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
}

Does not have to work for blocking IO. Use dirty tricks: override Thread.interrupt() close IO object, cause IOException that if properly handled may end thread run method.不必为阻塞 IO 工作。使用肮脏的技巧:覆盖 Thread.interrupt() 关闭 IO object,导致 IOException 如果处理得当可能会结束线程运行方法。

The elegant solution is to modify your fullRotate() method to throw InterruptedException.优雅的解决方案是修改您的 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();
}
  • When you call Thread.interrupt() you cause InterruptedException when any of the methods that throw it is invoked, in your case the Thread.sleep() or Thread.yield().当您调用 Thread.interrupt() 时,当任何抛出它的方法被调用时,您会导致 InterruptedException,在您的情况下是 Thread.sleep() 或 Thread.yield()。 This means that the best approach is to use it to actually interrupt the calculation.这意味着最好的方法是使用它来实际中断计算。
  • You still need to check Thread.currentThread().isInterrupted() if you want immediate response to your Thread.interrupt()你仍然需要检查 Thread.currentThread().isInterrupted() 如果你想立即响应你的 Thread.interrupt()
  • You can ether remove if(terminated) return;您可以删除 if(terminated) return; or substitute it with Thread.currentThread().isInterrupted() check.或者将其替换为 Thread.currentThread().isInterrupted() 检查。 Removing will be fine because the Thread.sleep(20)/Thread.yield() from fullRotate() will throw the InterruptedException.删除会很好,因为 fullRotate() 中的 Thread.sleep(20)/Thread.yield() 将抛出 InterruptedException。 Also code will be cleaner without all these if(terminated) all over the place.如果没有所有这些 if(terminated) 到处都是,代码也会更清晰。
  • Use Thread.yield() instead for Thread.sleep(20).使用 Thread.yield() 代替 Thread.sleep(20)。 Obviously you don't want to sleep, because you put 20 millis.显然你不想睡觉,因为你放了 20 毫秒。 20 milis is very close to the context switch time quantum. 20 milis 非常接近上下文切换时间量程。 The thread will ether sleep more, or less.线程将更多或更少地休眠。 You don't want it to sleep more without any reason, so use yield().你不希望它无缘无故地睡得更多,所以使用 yield()。

Your thread run() then becomes:你的线程 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(); 

Also you have to remove the try catch from the following:还必须从以下内容中删除try catch:

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

The only way to interrupt thread is to make it exit itself.中断线程的唯一方法是让它自己退出。 Strightforward interruption is not even implemented in Java because of deadlocks possibility.由于死锁的可能性,在 Java 中甚至没有实现直接中断。 So your thread code must look like:所以你的线程代码必须是这样的:

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

And somethingistrue is a kind of a signal for thread to interrupt. somethingistrue是线程中断的一种信号。

The only thing that can reliably stop the execution of one thread from another is the OS.唯一可以可靠地停止一个线程从另一个线程执行的是操作系统。 So, there are not many choices:所以,选择不多:

1) Signal the thread to stop itself. 1) 向线程发出停止自身的信号。 This scheme kinda depends on what the thread is doing.这个方案有点取决于线程在做什么。 If it's running on another processor or stuck on a blocking call you cannot unblock, (note-many blocking calls can be persuaded to return early), there can be problems.如果它在另一个处理器上运行或卡在无法解除阻塞的阻塞调用上(请注意,可以说服许多阻塞调用提前返回),可能会出现问题。

What is 'lot of stuff' doing? “很多东西”在做什么?

2) Use an OS call to terminate the thread. 2) 使用操作系统调用终止线程。 This can be a viable option, depending on what the thread does.这可能是一个可行的选择,具体取决于线程的作用。 If there is any possibility of terminating the thread while it holds a public lock on a vital resource, (eg. it's in the middle of a malloc() and has the memory-manager locked), then you can get into trouble.如果有任何可能在线程持有重要资源的公共锁时终止线程(例如,它在 malloc() 的中间并且已锁定内存管理器),那么您可能会遇到麻烦。 You have to be sure of what thread is doing to safely abort it in this way.您必须确定线程正在做什么才能以这种方式安全地中止它。

3) Use a separate process to run the 'stuff'. 3)使用单独的进程来运行“东西”。 This will obviously work OK, but usually involves slow and painful inter-process comms to pass data and return results.这显然可以正常工作,但通常涉及缓慢而痛苦的进程间通信来传递数据和返回结果。

4) Design the app so that it does not need to terminate the thread. 4)设计应用程序,使其不需要终止线程。 Some apps never need to terminate any threads except at app shutdown, so there's no problem - the OS can stop anything.有些应用程序不需要终止任何线程,除非在应用程序关闭时,所以没有问题——操作系统可以停止任何东西。 In those cases where a thread must be 'stopped' during an app run and is running a lengthy CPU-intensive operation or is blocked for a long and possibly indeterminate period, 'orphaning' a thread by setting its priority to minimum/idle and just leaving it to eventually die off is another common approach.在应用程序运行期间必须“停止”线程并且正在运行长时间的 CPU 密集型操作或被阻塞很长时间且可能不确定的情况下,通过将线程的优先级设置为最小/空闲来“孤立”线程让它最终消亡是另一种常见的方法。

The worst possible scenario is a thread running a lot of stuff for long time that uses the memory-manager or other public locks, possibly in a library where you don't know exactly what it's doing, can't be hooked and reads/writes data in such a way that 'orphaning' it off means that another thread cannot be started to use the data.最糟糕的情况是一个线程长时间运行大量的东西,它使用内存管理器或其他公共锁,可能在一个你不知道它在做什么的库中,不能被挂钩和读/写以“孤立”它的方式处理数据意味着无法启动另一个线程来使用该数据。 You're really stuft then and you may have to terminate the app and restart.你真的很笨,你可能不得不终止应用程序并重新启动。 It's just best to avoid designs where a thread can get into such a state:)最好避免线程可以进入这样的 state 的设计:)

5) Forgot one - if the thread is using data you can get at, setting something to NULL, 0, MaxInt or some other like bodge can cause an exception to be raised in the thread running the long stuff. 5) 忘记了 - 如果线程正在使用您可以获得的数据,将某些内容设置为 NULL、0、MaxInt 或其他类似 bodge 的内容可能会导致在运行长内容的线程中引发异常。 When execution bubbles out of long stuff, the thread can check the Interrupted state in the exception handler and exit if set.当执行从长内容中冒出来时,线程可以检查异常处理程序中的中断 state 并在设置时退出。

When a thread is running ( consuming CPU cycles ), then it will not by default ( automatically ) respond to Thread.interrupt() .当线程正在运行(消耗 CPU 周期)时,默认情况下它不会(自动)响应Thread.interrupt() You will have to write the code to do this explicitly.您将必须编写代码来明确地执行此操作。

Break up //do lot of stuff here for long time into 2 or more steps, and insert between these steps checks for the Thread.currentThread().isInterrupted() - if true - break out, else continue.//do lot of stuff here for long time分成 2 个或更多步骤,并在这些步骤之间插入检查Thread.currentThread().isInterrupted() - 如果为真 - 中断,否则继续。 This is only safe way to achieve what you want.这是实现您想要的唯一安全方法。

It depends on what the long running stuff is, you will have to design the steps and decide when its best to check for interruption and breakout.这取决于长期运行的东西是什么,您将必须设计步骤并决定何时最好检查中断和突破。

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

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