首页 > 解决方案 > 读取另一个线程同时写入的文件流

问题描述

我有一个BlobInputStream绑定到数据库事务的 Postgres,我需要将其传输到通过 HTTP 请求请求它的客户端。

为了避免慢速客户端饿死数据库事务,我想将流刷新到磁盘并同时让客户端从磁盘读取:这样,即使客户端仍在读取,事务也会在流写入磁盘时结束文件。

显然,我不希望客户端在开始读取之前等待整个流被刷新到磁盘。

到目前为止,这是我的代码:

public void transferStreamToChannel(InputStream stream, SinkChannel channel) {
    try {
        // Create a temporary file to buffer to stream transfer, so that slow readers won't
        // starve the transaction.
        var tmp = Files.createTempFile(StreamTransferInitiator.class.getSimpleName(),
                Thread.currentThread().getName());
        var tos = Files.newOutputStream(tmp);

        var executor = Executors.newSingleThreadExecutor();
        executor.execute(() -> {
            try (var fis = Files.newInputStream(tmp, StandardOpenOption.DELETE_ON_CLOSE)) {
                var out = Channels.newOutputStream(channel);
                fis.transferTo(out);
            } catch (IOException e) {
                this.getLogger().error("Error writing to disk", e);
            }
        });

        stream.transferTo(tos);
    } catch (IOException e) {
        this.getLogger().error("Error reading stream", e);
    } finally {
        try {
            stream.close();
            channel.close();
        } catch (IOException e) {
            this.getLogger().error("Error closing stream", e);
        }
    }
}

这样做的问题是执行程序会找到一个空文件,并且会在数据库流完全刷新之前关闭。

我怎样才能连接这两个操作,以便在传输到客户端时知道仍有更多数据要写入磁盘?

标签: javamultithreadingasynchronousjava-io

解决方案


推荐阅读