Java 线程中断并不总是有效的

Java 线程中断并不总是有效的,java,multithreading,Java,Multithreading,我有一个线程,它以固定的间隔发送UDP数据包。过了一会儿,我从另一个线程调用interrupt(),我希望发送方线程在此之后完全完成。大多数情况下,发送方线程在接收到中断后完成。但是,在某些罕见的情况下,发送方线程不会。你能帮我找出线程代码中的错误吗 try { DatagramSocket socket = null; Timber.d("Initialize the sender..."); while (!Thread.currentThread().isInte

我有一个线程,它以固定的间隔发送UDP数据包。过了一会儿,我从另一个线程调用interrupt(),我希望发送方线程在此之后完全完成。大多数情况下,发送方线程在接收到中断后完成。但是,在某些罕见的情况下,发送方线程不会。你能帮我找出线程代码中的错误吗

try {
    DatagramSocket socket = null;
    Timber.d("Initialize the sender...");

    while (!Thread.currentThread().isInterrupted()) {
        try {
            Timber.d("Sending UDP broadcasts...");
            socket = new DatagramSocket();

            while (!Thread.currentThread().isInterrupted()) {
                String s = "hello";
                byte[] buffer = s.getBytes();
                DatagramPacket packet = new DatagramPacket(
                        buffer, buffer.length,
                        mBroadcastAddress, PORT);
                try {
                    if (BuildConfig.DEBUG)
                        Timber.d("[" + new DateTime().toLocalTime() + "] " +
                                "Send UDP packet");
                    socket.send(packet);
                } catch (IOException ioe) {
                    Timber.d(ioe, "IOException");
                }
                Thread.sleep(TIMEOUT_SLEEP);
            }
        } catch (SocketException se) {
            Timber.d(se, "Socket exception");
            break;
        } finally {
            if (socket != null)
                socket.close();
            socket = null;
        }
    }
} catch (InterruptedException ie) {
    Timber.d("The sender thread received interrupt request");
}

Timber.d("Finish the sender...");

正如我所看到的,在代码的某些部分,您正在吞咽interruptedException。在捕获interruptedException后恢复中断,不要吞咽它。 这就是恢复中断的方式
Thread.currentThread().interrupt()

我认为问题在于:

    } catch (IOException ioe) {
        Timber.d(ioe, "IOException");
    }
问题是,
IOException
的子类型之一是<代码>中断异常。当抛出异常(响应中断)时,线程的
interrupted
标志被清除。现在,“非常不可能”,这个代码将在代码< >发送< /代码>调用中间被中断。但如果是这样,那么你将有效地“吃掉”一个中断

我认为您应该将上述内容更改为:

    } catch (InterruptedIOException ioe) {
        Thread.currentThread().interrupt();
    } catch (IOException ioe) {
        Timber.d(ioe, "IOException");
    }


此外,如果您稍后要测试中断标志,那么当您在代码段末尾捕捉到
InterruptedException
时,您也在“吃”它,您应该再次设置它。。。如上所述。

您确定正在调用中断吗?我认为调用interrupt()会触发InterruptedException,而不是InterruptedIOException。我应该理解send()方法将InterruptedException作为InterruptedIOException重新调用吗?实际上,
interrupt()
不一定会触发这些异常。IIRC中,是sleep/wait/etc方法的代码引发了
InterruptedException
,是IO调用的代码引发了
InterruptedException