@Override
    public void close() throws IOException {
        if (closed) {
            return;
        }

        if (buffer.position() > 0) {
            updateBuffer(false);
        }

        // buffer = ClickHouseByteBuffer.EMPTY_BUFFER;
        try {
            if (timeout > 0L) {
                if (!queue.offer(ClickHouseByteBuffer.EMPTY_BUFFER, timeout, TimeUnit.MILLISECONDS)) {
                    throw new IOException(ClickHouseUtils.format("Close stream timed out after %d ms", timeout));
                }
            } else {
                queue.put(ClickHouseByteBuffer.EMPTY_BUFFER);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("Thread was interrupted when putting EMPTY buffer into queue", e);
        } finally {
            closed = true;
            ClickHouseDataStreamFactory.handleCustomAction(postCloseAction);
        }
    }
A combination of {@link java.io.PipedOutputStream} and
{@link java.io.PipedInputStream} for streaming data between server and
client. To avoid dead lock and high memory usage, please make sure writer and
reader are on two separate threads.
clickhouse-data/src/main/java/com/clickhouse/data/stream/BlockingPipedOutputStream.java