如何避免将太多数据写入输出并阻止线程?

Fre*_*ind 6 java sockets blocking

在由线程池运行的任务中,我想将一堆字符串写入远程,并且有一个标志来指示任务是否已被取消.

我正在使用以下代码以确保我可以尽快停止:

public void sendToRemote(Iterator<String> data, OutputStream remote) {
    try {
        System.out.println("##### staring sending")
        while(!this.cancelled && data.hasNext()) {
            remote.write(data.next())
        }
        System.out.println("##### finished sending")
        System.out.println("")
    } catch(Throwable e) {
        e.printStackTrace();
    } finally {
        remote.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

我有时发现,如果我给这个方法提供一个非常大的数据(或无限的迭代器),即使我将其设置this.cancelledtrue以后,它也无法及时完成.代码似乎被阻止,经过很长一段时间(大约1分钟)后,会出现如下错误:

java.net.SocketTimeoutException: write blocked too long
Run Code Online (Sandbox Code Playgroud)

所以我想remote.write如果有太多的数据要发送,方法可能会阻塞自己,但是遥控器不会及时消耗它.虽然我设置this.cancelledtrue,但是该方法已经remote.write(data.next())在行中被阻塞了很长时间,所以它没有机会检查值this.cancelled并跳过循环.相反,最后,它会SocketTimeoutException在很长一段时间后抛出.

我的理解是否正确?如果是,如果有太多数据要发送,我怎么能避免阻塞?

Dex*_*ter 0

尝试简单地关闭远程 OutputStream。您的线程将以异常结束。

  1. Thread#1 忙于执行 sendToRemote();
  2. Thread#2 认为已经足够了并关闭了遥控器。(假设 OutPutStream 对象不是线程本地的,就像在某处的全局引用中一样)
  3. Thread#1 因异常而死亡:)

编辑我在互联网上找到了这个

启用延迟并将超时设置为特定秒数将导致后续对 Socket.Close 的调用阻塞,直到发送缓冲区中的所有数据均已发送或超时已过。