簡體   English   中英

如何在沒有關閉的情況下中斷被某個套接字IO操作阻塞的線程

[英]How to interupt a thread blocked by some socket IO operation without closing it

我真的想知道如何中斷被某些I / O操作阻塞的線程? I / O是通過套接字,我不想close()套接字。

我嘗試使用Thread.interrupt()來中斷線程,但沒有成功。

線程被IO操作阻止:

void run(){
    byte[] data=new byte[1024];
    in.read(data);//blocked!
}

用於中斷被阻塞線程的線程(不起作用):

void run(){
    blockedThread.interrupt();//no success!
}

如果您絕對不能/不想使用普通的Java Socket類關閉套接字,則可以使用java.nio.SocketChannel來使用套接字。

SocketChannel實現了InterruptibleChannel ,可以通過中斷等待套接字上的I / O的線程來關閉它。 在這種情況下,阻塞的讀取將拋出ClosedByInterruptException

在獲得SocketTimeoutException ,在套接字和循環上設置一個簡短的讀取超時,每次都檢查Thread.isInterrupted() 使用Thread.interrupt()來中斷線程。

您可以添加這樣的方法,因為任何阻塞IO操作都會拋出IOException: -

public void close() throws IOException {
    this.socket.close();
}

來自javadoc: -

關閉此套接字。 當前在accept()中被阻塞的任何線程都將拋出SocketException。

不幸的是,大多數平台上的sun java impl都沒有通過線程中斷處理io中斷(我相信你可以通過一些nio的東西得到這個,不確定)。 但是,我相信如果線程被阻塞從套接字讀取,並且你有一個該套接字的句柄,你可以從另一個線程異步關閉套接字(這將中斷被阻塞的線程)。

注意沒有聲明拋出InterruptedException

 public int read(byte[] b) throws IOException 

從輸入流中讀取一些字節數並將它們存儲到緩沖區數組b中。 實際讀取的字節數以整數形式返回。 此方法將阻塞,直到輸入數據可用,檢測到文件結尾或引發異常。

一些讀取方法將通過Thread#interrupt()響應外部中斷,關閉流或拋出異常。

如果沒有某種方式關閉或從另一個線程中提供流,或者使用Thread#stop()殺死該線程,則無法以其他方式停止此線程。 最后一種方法只是最后的手段,不應該出於各種原因使用。

類似於等待任何監視器的操作的I / O不可中斷,這是因為這些情況不需要InterruptedException rutine,但是根據Java 7 Documentation ,屬於nio包的I / O類可以響應任何嘗試插入其中一個流中斷異常,其中一個是ClosedByInterruptionException ,它的父類是AsynchronousCloseException

但是如果你想要關閉執行thead,而不是關閉流,你可以考慮使用提供取消方法的FutureTask

看一下這篇博文 ,特別是解決方案4 - NIO with Buffering

簡而言之:對於常規文件,您必須使用NIO ,使用擴展AbstractInterruptableChannelChannel ,例如。 FileChannel

使用套接字時,使用Socket#close()來中斷/關閉。

根據javadocs:

當前在此套接字上的I / O操作中阻塞的任何線程都將拋出SocketException。

但:

還有另一種方法可以解決這個問題:在NIO使用異步IO,請看這里 異步IO的問題是,它處理起來非常復雜(與阻塞IO相比),因為你不再繼續在流上中繼,而是緩沖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM