停止不包含while语句的线程

时间:2018-03-23 12:40:09

标签: java

所有答案都是关于如何停止某些线程的循环,但是如果我没有循环但是我还想在执行/处理所有行之前停止一个线程呢?

例如,我有一个通常运行7-10秒然后死掉(终止)的线程:

mThread = new Thread(new Runnable() {
   @Override
   public void run() {

    // some code here 
    // some here  
    // some here
    // some here          
    // some here
    // all lines takes about 7-10 seconds

   }
});

如果我开始一个线程,并且在2或3秒后我需要停止它,然后该怎么做并且不要等待10秒?

4 个答案:

答案 0 :(得分:3)

如果您的线程没有被阻止,并且实际上正在处理内容,那么中断它可能没有帮助。您可以对线程进行编码以检查当前线程上的中断标志,然后在看到该标志已设置时停止。

这是检查当前线程是否已被中断的方法。

Thread.currentThread().isInterrupted();

所以你必须像这样编写你的线程......

mThread = new Thread(new Runnable() {
   @Override
   public void run() {

    // some code here 
    if (Thread.currentThread().isInterrupted()) return;
    // some here  
    if (Thread.currentThread().isInterrupted()) return;
    // some here
    if (Thread.currentThread().isInterrupted()) return;
    // some here          
    if (Thread.currentThread().isInterrupted()) return;
    // some here
    // all lines takes about 7-10 seconds    
   }
});

然后你可以继续中断mThread,它会产生影响。虽然它仍将继续处理当前的some here步骤。

答案 1 :(得分:3)

说明

首选方法是在线程中实现停止机制。您也可以尝试观察interrupt标志。您可以使用Thread#interrupt方法从外部中断,并且线程可以使用Thread#isInterruptedThread#interrupted检查标记(请参阅Thread的文档)。

没有办法强制线程从外部停止,而线程实际上没有实现逻辑。有Thread#stop方法,但已弃用,绝不应使用。来自documentation

  

<强>已过时即可。此方法固有不安全。使用Thread.stop停止某个线程会导致它解锁所有已锁定的监视器(这是未经检查的ThreadDeath异常向上传播的自然结果)。如果先前受这些监视器保护的任何对象处于不一致状态,则受损对象对其他线程可见,可能导致任意行为。 stop的许多用法应该被简单修改某个变量的代码替换,以指示目标线程应该停止运行。目标线程应该定期检查此变量,并且如果变量指示它将停止运行,则以有序的方式从其run方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用中断方法来中断等待。有关详细信息,请参阅Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

解决方案

您可以像这样修改线程:

public class MyThread implements Runnable {
    private volatile boolean mShouldStop = false;

    public void shutdown() {
        mShouldStop = true;
    }

    @Override
    public void run() {
        // First line ...
        if (mShouldStop) return;
        // Second line ...
        if (mShouldStop) return;
        // Third line ...
        if (mShouldStop) return;
    }
}

因此,您需要定期检查标志,然后手动中止。

通常这样的线程有某种while (true)循环。在这种情况下,你可以做到更容易:

@Override
public void run() {
    while (!mShouldStop) {
        // Do something ...
    }
}

根据您的应用程序,您可能会将中断标志解释为线程关闭的信号。然后你的代码看起来像

@Override
public void run() {
    while (!Thread.interrupted()) {
        // Do something ...
    }
}

注意

mShouldStop必须为volatile,以确保Thread正确更新。请参阅Oracle的教程Atomic Access

答案 2 :(得分:0)

您使用mThread.interrupt()中断线程。但是,为了使其正常工作,您的线程需要检查中断状态(通过休眠)。看看这个thread

有关详细信息,请参阅此thread

答案 3 :(得分:0)

您需要检查线程中的中断状态。像这样的东西

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class ThreadInterruptor {


    private static class Worker implements Runnable {
        @Override
        public void run() {
            while (true) {
                IntStream.range(0, Short.MAX_VALUE).forEach(i ->noop());
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("i got interrupted");
                    break;
                }
            }
        }
        private void noop(){}
    }


    public static void main(String[] args) throws Exception{
        Thread thread = new Thread(new Worker());
        thread.start();
        TimeUnit.SECONDS.sleep(5);
        thread.interrupt();
    }

}