【问题标题】:Interrupt a thread safely in Java在 Java 中安全地中断线程
【发布时间】:2015-03-16 14:50:42
【问题描述】:

有一个线程连接到服务器(HTTP)并在循环中等待响应或响应超时(服务器直到有数据返回时才响应)。如果响应返回一个线程处理它。

在服务停止时,需要停止/中断所有线程,但线程必须完成响应处理(如果线程正在处理而不仅仅是等待响应)。

这是代码示例

public class WaitingResponseThread extends Thread {

    static final int TIMEOUT = 4 * 1000;
    static final int PROCESSING_DURATION = 2000;

    private volatile boolean stopped = false;
    private volatile boolean processing = false;

    public void run() {
        System.out.println("starting child thread");
        while(!stopped) {
            try {
                // here a thread is awaiting server response (in real life response timeout is 400 sec)
                // probably it is safe to interrupt the thread now
                // emulating this with Thread.sleep() 
                System.out.println("awaiting response");
                Thread.sleep(TIMEOUT);

                processing = true;

                // there is some job on response and we must allow it to finish the job
                // again emulating delay with Thread.sleep()
                Thread.sleep(PROCESSING_DURATION);

                processing = false;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("ending child thread");
    }

    public void setStopped(boolean stopped) {
        this.stopped = stopped;
    }

    public boolean isProcessing() {
        return processing;
    }

    public static void main(String[] args) {
        WaitingResponseThread t = new WaitingResponseThread();

        // starting thread, it sends a request and waits for a response
        t.start();

        try {
            Thread.sleep(1);

            // let's allow the thread to finish normally in case it is processing response
            t.setStopped(true);

            System.out.println("awaiting child thread to get response");
            Thread.sleep(TIMEOUT + 1);

            // let's allow the thread to finish processing
            while(t.isProcessing()) {
                System.out.println("processing");
                Thread.sleep(500);
            }

            // we can't wait for 400sec until the next loop check
            // so as the thread is sleeping we just interrupting it
            if(t.isAlive()) {
                System.out.println("killing");
                t.interrupt();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("ending main thread");
    }
}

这种“中断”方法好吗?是否有另一种方法可以不等待超时并且不丢失正在处理的数据?

【问题讨论】:

  • 另一种方法是使用 Executors docs.oracle.com/javase/8/docs/api/java/util/concurrent/… 然后您可以调用 yourPool.shutdown()yourPool.awaitTermination(time, unit) 但您仍然需要正确处理每个线程中的中断,据我所知没有铸铁方式来确保螺纹始终正确完成。而不是重新发明轮子。
  • 如果您仍想完成当前 HTTP 请求的处理,interrupt 方法不是一个好的选择。原因是调用interrupt会导致线程上IO操作的InterruptedIOException被中断,终止IO尝试(并且HTTP请求涉及IO)
  • @gumkins 但你只开始一个线程!?你说的“线程列表”在哪里?
  • @isnot2bad,这是一个简化的例子。实际上,我并没有试图将您的注意力集中在多个线程之间的资源共享上。我只需要安全地停止线程。但是您可以想象 ArrayList 及其在 main() 方法中对 t.start()、t.setStopped(true)、t.isProcessing() 和 t.interrupt() 的迭代。为了正义,我修改了主题和描述,但现在恐怕有人会问我为什么需要 1 个线程:-)

标签: java multithreading


【解决方案1】:

这个

while(t.isProcessing()) {
    System.out.println("processing");
    Thread.sleep(500);
}

是一种轮询形式。您应该不惜一切代价避免投票。如果可能,请使用一种委托形式,其中被调用者在处理完成后通知调用者。

除此之外,我很确定中断线程是你也很少想要做的事情,但是如果你不得不这样做的话,你这样做的方式很好。

【讨论】:

  • 你好 Warkst!对我知道那个。我只是想最小化代码示例。谢谢!
【解决方案2】:

Thread 类有几个函数可以在中断时使用。

  • 捕获InterruptionException
  • 使用方法isInterrupted() (not static)
  • 使用方法interrupted() (static)
  • 检查interrupted()isInterrupted(),然后检查throw new InterruptedException()

有了这些,你可能可以让你的线程在杀死它之前完成当前的工作,可能在 catch 子句中。

【讨论】:

    猜你喜欢
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多