Java 日看一类(42)之IO包中的PipedInputStream

微信小程序推广策略,打开小程序领域流量大门 本文旨在为小程序开发者、运营者和企业主提供一套完整的微信小程序推广策略体系,帮助他们在竞争激烈的小程序生态中获得更多流量和用户。内容涵盖从0到1的冷启动策略,到成熟期的增长技巧。本文将首先介绍小程序的基础推广设置,然后深入探讨各种流量获取渠道,接着分析数据驱动的优化方法,最后展望未来发展趋势。小程序:无需下载安装即可使用的应用,运行在微信生态内:独立访客数:页面浏览量转化率:完成目标行为的用户比例留存率:用户在一定时间后仍活跃的比例自然流量获取:通过优化搜索、完善资料等方式获得基础流量社交裂变。 阅读详情

该类继承自InputStream

无引入包



该类的类头注释如下:

/**
 * A piped input stream should be connected
 * to a piped output stream; the piped  input
 * stream then provides whatever data bytes
 * are written to the piped output  stream.
 * Typically, data is read from a <code>PipedInputStream</code>
 * object by one thread  and data is written
 * to the corresponding <code>PipedOutputStream</code>
 * by some  other thread. Attempting to use
 * both objects from a single thread is not
 * recommended, as it may deadlock the thread.
 * The piped input stream contains a buffer,
 * decoupling read operations from write operations,
 * within limits.
 * A pipe is said to be <a name="BROKEN"> <i>broken</i> </a> if a
 * thread that was providing data bytes to the connected
 * piped output stream is no longer alive.
 *
 * @author  James Gosling
 * @see     java.io.PipedOutputStream
 * @since   JDK1.0
 */

大意如下:

一个管道输入流需要与管道输出流链接

管道输入流会获得管道出流被写入的任意byte数据

典型情况下,数据通过PipedInputStream被读取(单线程)并且数据被对应的PipedOutputSream写出

尝试通过单线程使用这两个对象是不推荐的

可能会造成线程的死锁

这个管道输入流包括了一个缓冲区,在缓冲区内可以分离读操作和写操作

如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏



该类含有如下的成员变量:

写关闭标志位

boolean closedByWriter = false;

读关闭标志位(要求每次都读取,敏感信息)

volatile boolean closedByReader = false;

连接状态

boolean connected = false;

读线程

Thread readSide;

写线程

Thread writeSide;

默认缓冲区大小

private static final int DEFAULT_PIPE_SIZE = 1024;

共用的管道缓冲区大小

protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE;

循环缓冲区

protected byte buffer[];

读取指针的偏移量

protected int in = -1;

写出指针的偏移量

protected int out = 0;



该类含有如下的成员方法:

构造函数(默认缓冲区大小

public PipedInputStream(PipedOutputStream src) throws IOException {
    this(src, DEFAULT_PIPE_SIZE);
}

构造函数(指定缓冲大小

public PipedInputStream(PipedOutputStream src, int pipeSize)
        throws IOException {
     initPipe(pipeSize);
     connect(src);
}

构造函数(暂时无链接,默认大小

public PipedInputStream() {
    initPipe(DEFAULT_PIPE_SIZE);
}

构造函数(同上,指定大小

public PipedInputStream(int pipeSize) {
    initPipe(pipeSize);
}

管道初始化函数(构造函数提取出的公因数

private void initPipe(int pipeSize) {
     if (pipeSize <= 0) {//检查缓冲区大小合理性
        throw new IllegalArgumentException("Pipe Size <= 0");
     }
     buffer = new byte[pipeSize];//初始化缓冲区
}

链接两个未被链接的管道(如果已链接就抛IOException

public void connect(PipedOutputStream src) throws IOException {
    src.connect(this);
}

接收一个byte数据(该方法会被阻塞,在没有有效输入时

protected synchronized void receive(int b) throws IOException {
    checkStateForReceive();//检查接收状态
    writeSide = Thread.currentThread();//获得当前的操作线程
    if (in == out)//如果写入指针和写出指针指向一个地方表示当前缓冲区满,无法接收
        awaitSpace();
    if (in < 0) {//如果输入指针小于0(为空),则初始化
        in = 0;
        out = 0;
    }
    buffer[in++] = (byte)(b & 0xFF);//将输入byte写入缓冲区
    if (in >= buffer.length) {//检查输出指针是否溢出,溢出则归0,可以使用in%=buffer.length,不过这样的操作效率就会变低
        in = 0;
    }
}

接收一个数组数据(也会被阻塞

synchronized void receive(byte b[], int off, int len)  throws IOException {
    checkStateForReceive();
    writeSide = Thread.currentThread();
    int bytesToTransfer = len;//获得需要写入的数据长度
    while (bytesToTransfer > 0) {//长度有效
        if (in == out)//满了
            awaitSpace();
        int nextTransferAmount = 0;//下次最多可写入的长度(因为可能存在写入长度超过缓冲区长度,所以分多次写入,每次写入都会覆盖上次的数据,需要在写入之前读取出上次的数据)
        if (out < in) {//in指针比较靠前
            nextTransferAmount = buffer.length - in;//获得剩余填充的数值长度
        } else if (in < out) {
            if (in == -1) {//缓冲区为空
                in = out = 0;
                nextTransferAmount = buffer.length - in;//获得缓冲区长度
            } else {
                nextTransferAmount = out - in;//获得可读取长度(如果读取到out就证明缓冲区已经读满了,再读入会影响数据
            }
        }
        if (nextTransferAmount > bytesToTransfer)//可一次写入
            nextTransferAmount = bytesToTransfer;
        assert(nextTransferAmount > 0);//断言大于0,在这里减少数值有效性检查,提高运行效率
        System.arraycopy(b, off, buffer, in, nextTransferAmount);
        bytesToTransfer -= nextTransferAmount;//获得剩余需转移数据
        off += nextTransferAmount;//修改需要读取的位置
        in += nextTransferAmount;
        if (in >= buffer.length) {//循环
            in = 0;
        }
    }
}

检查缓冲区状态

private void checkStateForReceive() throws IOException {
    if (!connected) {//连接状态检查
        throw new IOException("Pipe not connected");
    } else if (closedByWriter || closedByReader) {//管道被单方关闭
        throw new IOException("Pipe closed");
    } else if (readSide != null && !readSide.isAlive()) {//读取线程不存在或者挂了
        throw new IOException("Read end dead");
    }
}

阻塞写入操作

private void awaitSpace() throws IOException {
    while (in == out) {
        checkStateForReceive();//检测有效性

        /* full: kick any waiting readers */
        notifyAll();//唤醒所有阻塞线程(实质只找一个,但是赋予所有线程争夺权
        try {
            wait(1000);//挂起线程(丢失锁的竞争权
        } catch (InterruptedException ex) {//抛IO中断
            throw new java.io.InterruptedIOException();
        }
    }
}

关闭写入,唤醒所有挂起的线程

synchronized void receivedLast() {
    closedByWriter = true;
    notifyAll();
}

向管道中写入数据

public synchronized int read()  throws IOException {
    if (!connected) {//连接状态
        throw new IOException("Pipe not connected");
    } else if (closedByReader) {//读取方向关闭
        throw new IOException("Pipe closed");
    } else if (writeSide != null && !writeSide.isAlive()
               && !closedByWriter && (in < 0)) {//没有写入方且写出线程不存在,且写入线程未关闭,且未被初始化
        throw new IOException("Write end dead");
    }

    readSide = Thread.currentThread();//获得读取线程
    int trials = 2;//两次尝试机会,判定写线程“活性”
    while (in < 0) {//缓冲区为空
        if (closedByWriter) {//写入流关闭,标识文件已经读完(空文件
            /* closed by writer, return EOF */
            return -1;
        }
        if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {//写线程存在且并未活动且标志位小于0,管道断裂
            throw new IOException("Pipe broken");
        }
        /* might be a writer waiting */
        notifyAll();//唤醒所有的线程来竞争锁
        try {
            wait(1000);//挂起该读取方法
        } catch (InterruptedException ex) {
            throw new java.io.InterruptedIOException();
        }
    }
    int ret = buffer[out++] & 0xFF;//读出单个byte
    if (out >= buffer.length) {//循环
        out = 0;
    }
    if (in == out) {//读取完全部数据,置为空,方便操作
        /* now empty */
        in = -1;
    }

    return ret;//返回读取值
}

读取数组

public synchronized int read(byte b[], int off, int len)  throws IOException {
    if (b == null) {//传入数组有效性
        throw new NullPointerException();
    } else if (off < 0 || len < 0 || len > b.length - off) {//下标有效性
        throw new IndexOutOfBoundsException();
    } else if (len == 0) {//长度有效
        return 0;
    }

    /* possibly wait on the first character */
    int c = read();//读取单个字节
    if (c < 0) {//判断文件是否读取完毕
        return -1;
    }
    b[off] = (byte) c;
    int rlen = 1;//实际读出的数据长度
    while ((in >= 0) && (len > 1)) {//缓冲区不为空且剩余需读取长度部不为0

        int available;//每次可以读出的有效长度

        if (in > out) {
            available = Math.min((buffer.length - out), (in - out));
        } else {
            available = buffer.length - out;
        }

        // A byte is read beforehand outside the loop
        if (available > (len - 1)) {//单次可读出的有效长度大于剩余需求长度
            available = len - 1;
        }
        System.arraycopy(buffer, out, b, off + rlen, available);
        out += available;
        rlen += available;
        len -= available;

        if (out >= buffer.length) {
            out = 0;
        }
        if (in == out) {
            /* now empty */
            in = -1;
        }
    }
    return rlen;//返回实际读取长度
}

返回可以不受阻塞地读取出的数值数

public synchronized int available() throws IOException {
    if(in < 0)
        return 0;
    else if(in == out)//当两个相同时则为满(因为如果输出操作将指针修改成相等状态时会将in修改为-1,标志为空)
        return buffer.length;
    else if (in > out)
        return in - out;
    else
        return in + buffer.length - out;
}

关闭管道

public void close()  throws IOException {
    closedByReader = true;//读取方关闭
    synchronized (this) {//输入流置空,清空缓冲内有效数据
        in = -1;
    }
}




该类实质是一个带有线程同步的循环数组,理解这个之后其实非常简单。该类主要用于进程间通信,需要注意的是一个管道必须要有两端才能成立,否则是不成立的。文中的写入写出输入输出可能会看的头晕,在阅读是可以思考一下,这个操作的主语是谁,是谁在操作,操作的又是谁,这些说法是从主语角度来写的。


Ollama + OpenCLAW 在 Windows 系统的完整部署指南 Windows 部署优先选 WSL2,避免原生环境的权限/兼容性问题;网络问题通过“离线包+国内镜像”解决,版本问题通过升级 Node.js 解决;内存不足可切换轻量模型或增大 WSL2 内存分配;核心链路:Ollama(模型管理)→ Gateway(网关)→ OpenCLAW TUI(交互),各组件启动正常即可稳定使用。 阅读详情

相关推荐

设备树实践:从零构建一个嵌入式板级的设备树描述

本文详细介绍了如何从零开始为嵌入式Linux系统构建设备树(Device Tree),以i.MX6ULL处理器为例,涵盖硬件分析、设备树语法、外设配置及调试技巧。通过实践指导,帮助开发者掌握设备树编写,实现硬件与软件的高效对接,提升嵌入式开发效率。

plum99的博客 307

记录一下java使用jcraft/jsch连接sftp异常信息

java 连接sftp操作异常,数字异常信息

weixin_42564841的博客 4624

阻容降压 vs 开关电源:5V小功率供电方案成本与安全深度对比

本文深度对比了阻容降压电路与开关电源在5V小功率供电方案中的核心差异。重点剖析了二者在成本、体积、效率、温升及安全隔离等方面的优劣,并结合智能温控器、LED驱动等典型应用场景,为硬件工程师提供了清晰的选型决策框架,帮助在成本与安全之间做出最佳权衡。

weixin_29310631的博客 702

Java中IO框架——PipedInputStream/PipedOutputStream源码解析

PipedInputStream 继承自 InputStream 类。 PipedOutputSteam 继承自 OutputStream 类。 在使用管道通信时,必须将 PipedOutputStream 和 PipedInputStream 配套使用。它们的作用是让多线程可以通过管道进行线程间的通讯。 使用管道通信时,大致的流程是:在线程A中向 PipedOutputStream 中写入数

在梅边的专栏 459

Widar3.0复现日志(DFSExtractionCode)

需要使用的matlab基本功能

XiaoQiXiaoWei_J的博客 2439

实用电路精讲系列---仪表放大器

摘要 仪表放大器通过三级运放架构实现高共模抑制比(CMRR>100dB)和精密差分放大,其核心是第一级同相运放提供高输入阻抗和可调增益(G=1+2R/RG),第二级差分运放消除共模干扰。具有低失调(≤50μV)、低温漂(≤0.6μV/℃)特性,广泛应用于智能断路器电流监测、ECG心电信号放大等场景。典型电路采用LTC1049运放,通过匹配电阻网络实现199倍差分增益,结合输出缓冲确保信号稳定性。设计时需注意输入共模电压范围限制和增益电阻精度,优选集成IC(如AD620、INA128)以规避分立元件匹配

weixin_40590799的博客 2078

java io PipedInputStream源码分析

目录 简介 字段closedByWriter,closedByReader,connected,readSide,writeSide,buffer,in,out 4个构造函数,方法initPipe,connected 2个receive方法,checkStateForReceive方法,awaitSpace方法,receivedLast方法 2个read方法,available方法,close方法 简介 package java.io; /** * 管道输入流应该连接到管道输出流;

今天吃了吗的博客 484

【Bug已解决】zsh: command not found: claude 解决方案

方案适用场景推荐指数难度方案一:配置 npm 全局目录所有平台,长期使用⭐⭐⭐⭐⭐低方案二:修复 PATH 变量快速修复,不想改 npm 配置⭐⭐⭐⭐低方案三:重建软链接文件存在但链接断裂⭐⭐⭐中方案四:nvm 专属方案使用 nvm 管理多版本 Node.js⭐⭐⭐⭐低方案五:Windows 专属Windows 系统⭐⭐⭐⭐⭐低方案六:Homebrew 安装macOS 用户,npm 有问题⭐⭐⭐低根本原因。

博客 1万+

日期反序列化

package com.clamc.config; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.spring...

732

高通SDX35:SGMII接口PHY RTL8211FSI-CG驱动适配

高通SDX35 RTL8211F SGMII

不秃头的程序猿Gabriel的博客 787

【制作100个unity实战之2】实现一款简单的FPS游戏

你将学到: fps武器脚本 基础瞄准功能 僵尸敌人AI 巡逻范围 攻击间 搜寻半径 追击 枪声吸引周围的僵尸 击中僵直效果

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 3553

[七]JavaIO之 PipedInputStream 和 PipedInputStream

  管道简介   管道的含义,很久之前就已经出现 用于表示数据直接交互 它的含义与平时说的管道的含义是类似的,就是直连 JavaIO中的 PipedInputStream 和 PipedOutputStream 就是IO体系中字节流的管道         java中,PipedOutput...

weixin_34099526的博客 350

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Java 日看一类(43)之IO包中的PipedOutputStream类

该类继承自OutputStream引入了IO包(本来就是这个包里的,引得没看懂)该类的类头注释如下:/** * A piped output stream can be connected to a piped input stream * to create a communications pipe. The piped output stream is the * sending en...

github_37666068的博客 429

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

java IO笔记(PipedInputStream/PipedOutputStream)

在上一篇笔记中讲述了java io 中的文件(file)以及如何用文件流来对文件进行读写操作,本篇则要讲述的是java IO中的管道流。 java IO中的管道流可以使得同一进程中的不同线程进行通信,如果不明白进程和线程的区别的话,可以去网上搜搜资料,可以看做提供同一jvm的通信能力。在java IO中管道的创建需要通过PipedInputStream和PipedOutputStream两个类,

moonfish0607的博客 853

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Java中的管道流 PipedOutputStream和PipedInputStream

我们在学习IO流的时候可能会学字节流、字符流等,但是关于管道流的相信大部分视频或者教程都是一语带过,第一个是因为这个东西在实际开发中用的也不是很多,但是学习无止境,存在既有理。JDK中既然有个类那说明他并不是一无是处,只是我们目前还没有场景用到它,那说明我们说的还不够,知识点还不足以去驾驭它。 管道流其实是一个很有魅力的流,用法也很独特。他用来连接两个线程之间的通信,比如传输文件等。它们的作...

坐看云起时_雨宣 1万+

Java IO(RandomAccessFile、File、PipedInputStream、PipedOutputStream)

RandomAccessFile RandomAccessFile允许你来回读写文件,也可以替换文件中的某些部分。FileInputStream和FileOutputStream没有这样的功能。 在使用RandomAccessFile之前,必须初始化它。 RandomAccessFile file = new RandomAccessFile("c:\\data\\file.txt", "rw"); 请注意构造函数的第二个参数:“rw”,表明你以读写方式打开文件。 1.1 在RandomAcc

chenbin1991smile的博客 334

Java IO操作——线程间通讯流(管道流 PipedOutputStream、PipedInputStream)

管道流 管道流的作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream)、管道输入流(PipedInputStream)如果要想进行管道输出,则必须把输出流连在输入流之上,在PipedOutputStream中有一个方法用于连接管道: public void connect(PipedInputStream snk) throws IOException

1976

Java IO PipedInputStream与 PipedOutputStream

PipedOutputStream 源码解析 /** * 1. 可以将一个管道输出流连接到一个管道输入流,来创建一个通信管道。管道的数据发送端为管道输出流。 * 2. 通常,一个线程将数据写入到管道输出流(PipedOutputStream),其他线程可以通过与管道输出流相连接的管道输入流(PipedInputStream)来读取数据。 * 3. 不推荐在一个线程中同时使用管道输入输出流,可能会导致死锁。 * 4. 如果从相连接的管道输入流读取数据的线程已经不再存活,那么就代表这个管道已经损坏。

i余数的博客 323

Java IO - PipedOutputStream & PipedInputStream

基本概念 PipedOutputStream & PipedInputStream (管道字节输入流&管道输出字节流)是配套使用的。可以将管道输出流连接到管道输入流来创建通信管道。 通常的用法是让两个线程分别操作输入输出流,由输出流向管道写入数据,然后再由输出流从管道中读取数据。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。 继承关系: 实例探究1.生产者&消费者 定义两个线程代

一把空心菜 683

Java_io体系之PipedInputStream、PipedOutputStream简介、走进源码及示例——06

Java_io体系之PipedInputStream/PipedOutputStream简介、走进源码及示例——06        ——管道输出流、必须建立在管道输入流之上、所以先介绍管道输出流。可以先看源码或者总结、总结写的有点Q、不喜可无视、有误的地方指出则不胜感激。 一:PipedOutputStream 1、       类功能简介: 管道字节输出流

Oscar Chen 2465

Java PipedInputStream available()方法与示例

PipedInputStream类的available()方法 (PipedInputStream Class available() method) available() method is available in java.io package. available()方法在java.io包中可用。 available() method is used to return the n...

cumt951045的博客 413

Java IO流之PipedOutputStream和PipedInputStream分析

  简介     PipedOutputStream和PipedInputStream分别是管道输出流和管道输入流,是字节流的一种。两者配合使用可以进行同一个进程不同线程之间的通信,管道输入流用于向管道中读取数据,管道输出流用于向管道中写入数据。通常管道输入流和管道输出流在不同的线程中,如果在同一个线程可能存在死锁的情况。     实现方式大致是,管道输出流与管道输出流进行关联,当一个线程向...

梦悠哉的博客 1380

Java.PipedInputStream-PipedOutputStream

<br />PipedInputStream和PipedOutStream类用于在应用程序中创建管道通信<br />一个PipedOutputStream必须与一个PipedInputStream连接建立一个通信管道<br />PipedOutputStream可以向管道中写入数据,PipedInputStream可以从管道中读取PipedOutputStream写入的数据。这两个类主要用来完成线程之间的通信。一个线程的管道输入流可以从另一个线程的管道输出流中读取数据<br />PipedWriter和Pi

CodeAnt的专栏 2499

java文件io管道(PipedInputStream和PipedOutputStream)介绍及使用

简介 PipedOutputStream和PipedInputStream分别是管道输出流和管道输入流。它们的作用是让多线程可以通过管道进行线程间的通讯。在使用管道通信时,必须将PipedOutputStreamPipedInputStream配套使用。使用管道通信时,大致的流程是:在线程A中写入数据,这些数据会存储在PipedInputStream的缓冲区中;此时,线程B通过读取PipedInp...

weixin_42738587的博客 1757

【Java笔记】IO管道流 PipedOutputStream和PipedInputStream

目录一、管道流代码二、注意事项1.输入方连接输入(out连in)2没连接抛异常(connect) 一、管道流代码 package io; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; /** * @ClassName: PipedStreamDome * @Author: Xlu103 * @Date: 2020-06-03 22:39 **/ publ

weixin_43493559的博客 429

Java IO:PipedOutputStream和PipedInputStream使用详解及源码分析

1 使用方法  PipedOutputStream和PipedInputStream是管道输出流和管道输入流,配合使用可以实现线程间通信。 使用管道实现线程间通信的主要流程如下:建立输出流out和输入流in,将out和in绑定,out中写入的数据则会同步写入的in的缓冲区(实际情况是,out中写入数据就是往in的缓冲区写数据,out中没有数据缓冲区)。1.1 方法介绍  PipedOutputSt

ahsxsk的学习之路 7752
上一篇: Java 日看一类(41)之IO包中的OutputStreamWriter类
下一篇: Java 日看一类(43)之IO包中的PipedOutputStream类
wyf95278
博客等级 码龄10年 38粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值