java多线程之PipedOutputStream和PipedInputStream

1 多线程之间如果想要通讯,可以通过管道流来实现,例如两个子线程之间想要互通数据,可以通过管道流(PipedOutputStream和PipedInputStream)来实现数据互通,PipedOutputStream负责write,PipedInputStream负责read。同时将PipedOutputStream和PipedInputStream进行连接。
如:public class TestMain {


public static void main(String[] args) {
PipedOutputStream pipedOutputStream=new PipedOutputStream();//管道输出流
PipedInputStream pipedInputStream=new PipedInputStream();//管道输入流
try {
pipedOutputStream.connect(pipedInputStream);//通过connect方法将管道输出流和管道输入流连接起来
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SenderThread senderThread=new SenderThread(pipedOutputStream);//创建构造方法,将其管道输出流作为参数
ReceiverThread receiverThread=new ReceiverThread(pipedInputStream);//创建构造方法,将其管道输入流作为参数
senderThread.start();
receiverThread.start();
}
}


SenderThread类:
public class SenderThread extends Thread{


private PipedOutputStream pipedOutputStream=null;

public SenderThread(PipedOutputStream pipedOutputStream_){
this.pipedOutputStream=pipedOutputStream_;
}


@Override
public void run() {
// TODO Auto-generated method stub
//super.run();
System.out.println("发送程序启动...");
if(pipedOutputStream==null){

}else{
String neirong1="abcdefg";
String neirong="";
for(int i=0;i<102;i++){
neirong=neirong+"0123456789";
}
neirong=neirong+neirong1;
try {
Thread.sleep(2*1000);
pipedOutputStream.write(neirong.getBytes());//管道输出流的write方法
pipedOutputStream.flush();
pipedOutputStream.close();
System.out.println("发送了:"+neirong);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


}


ReceiverThread类:
public class ReceiverThread extends Thread{


private PipedInputStream pipedInputStream=null;

public ReceiverThread(PipedInputStream pipedInputStream_){
this.pipedInputStream=pipedInputStream_;
}


@Override
public void run() {
// TODO Auto-generated method stub
//super.run();
System.out.println("接收程序启动....");
if(pipedInputStream==null){

}else{
//第一种尝试
byte[] byte_s=new byte[1024];
int num_receiver=0;
try {
num_receiver=pipedInputStream.read(byte_s);//管道输入流的read方法
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("接收到:"+new String(byte_s,0,num_receiver));
}
}
}


2 PipedOutputStream类的write可以将其内容写入到管道中,PipedInputStream类的read方法可以从管道中读取数据。同时read方法是线程安全的阻塞方法,如果没有可读取的会一直等待,直到有可读取的数据为止。
如: byte[] byte_s=new byte[1024];
int num_receiver=0;
try {
//此方法是线程安全的阻塞方法,如果没有可读取的数据会一直等待,直到有可读取的数据为止。
num_receiver=pipedInputStream.read(byte_s);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("接收到:"+new String(byte_s,0,num_receiver));


3 PipedInputStream类的管道缓存容量都是固定的是1024字节。就是说最多只能读取1024字节的数据。所以为了读取更多的数据,可以通过循环的方式来不断的读取1024字节长度的数据。
如: while(true){//循环来不断的读取数据。
try {
Thread.sleep(100);
byte[] byte_s=new byte[1024];
int num_re=pipedInputStream.read(byte_s);
if(num_re<=0){

}else{
System.out.println("接收了:"+new String(byte_s,0,num_re));
}

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


4 PipedInputStream中除了用read来读取数据外,还有一种判断是否可以读取数据的方法:avaliable()。该方法返回可读取的数据的长度。该方法是非阻塞的方法。如果没有可读取的数据长度会立刻返回0。表示可读取的数据长度为0。如果有可读取的数据,则返回可读取数据的长度。所以亦可以通过循环来不但的判断有可读取数据的长度。
如: while(true){
try {
Thread.sleep(100);
int num_re=-1;
byte[] byte_s=new byte[1024];
//通过循环来不断的判断是否有可读取的数据。
while((num_re=pipedInputStream.available())<=0){
Thread.sleep(200);
}

num_re=pipedInputStream.read(byte_s);
System.out.println("接收了:"+new String(byte_s,0,num_re));

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}


总结: PipedInputStream中有两个可使用的方法来读取数据,
read方法:线程安全的阻塞方法,会一直等待可读取的数据,如果没有会一直等待,直至有可读取的数据。
avaliable方法:立刻返回,一般通过循环来不断的判断,该方法返回可读取的数据的长度。


注意:因为管道流最多只能每次接受1024字节长度的数据,故如果接收的数据会分散。
如果数据用于连续的那种(如音频、视频等)可以使用管道流。
如果数据用于list或map或集合类型的完整的数据,则可以通过虚拟锁(一个类的某个属性添加虚拟锁,然后一个线程专门向这个属性添加值,一个线程专门从这个属性中取值,对这个属性添加了虚拟锁)的方式来使用。


故:多个子线程的数据互通还是使用虚拟锁的那种方式来实现比较好(或者使用基于链表的线程安全的队列如:LinkedBLockingQueue)。除非数据是音频或视频的那种。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值