管道Pipe
管道Pipe
java.nio.channels包中含有一个名为Pipe(管道)的类。广义上讲,管道就是一个用来在两个实体之间单向传输数据的导管。管道的概念对于Unix(和类Unix)操作系统的用户来说早就很熟悉了。Unix系统中,管道被用来连接一个进程的输出和另一个进程的输入。Pipe类实现一个管道范例,不过它所创建的管道是进程内(在Java虚拟机进程内部)而非进程间使用的。
参见图3-10。
/*
* @(#)Pipe.java 1.21 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/ package java.nio.channels; import java.io.IOException;
import java.nio.channels.spi.*; /**
* A pair of channels that implements a unidirectional pipe.
*
* <p> A pipe consists of a pair of channels: A writable {@link
* Pipe.SinkChannel </code>sink<code>} channel and a readable {@link
* Pipe.SourceChannel </code>source<code>} channel. Once some bytes are
* written to the sink channel they can be read from source channel in exactly
* the order in which they were written.
*
* <p> Whether or not a thread writing bytes to a pipe will block until another
* thread reads those bytes, or some previously-written bytes, from the pipe is
* system-dependent and therefore unspecified. Many pipe implementations will
* buffer up to a certain number of bytes between the sink and source channels,
* but such buffering should not be assumed. </p>
*
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @version 1.21, 05/11/17
* @since 1.4
*/ public abstract class Pipe { /**
* A channel representing the readable end of a {@link Pipe}. </p>
*
* @since 1.4
*/
public static abstract class SourceChannel
extends AbstractSelectableChannel
implements ReadableByteChannel, ScatteringByteChannel
{
/**
* Constructs a new instance of this class.
*/
protected SourceChannel(SelectorProvider provider) {
super(provider);
} /**
* Returns an operation set identifying this channel's supported
* operations.
*
* <p> Pipe-source channels only support reading, so this method
* returns {@link SelectionKey#OP_READ}. </p>
*
* @return The valid-operation set
*/
public final int validOps() {
return SelectionKey.OP_READ;
} } /**
* A channel representing the writable end of a {@link Pipe}. </p>
*
* @since 1.4
*/
public static abstract class SinkChannel
extends AbstractSelectableChannel
implements WritableByteChannel, GatheringByteChannel
{
/**
* Initializes a new instance of this class.
*/
protected SinkChannel(SelectorProvider provider) {
super(provider);
} /**
* Returns an operation set identifying this channel's supported
* operations.
*
* <p> Pipe-sink channels only support writing, so this method returns
* {@link SelectionKey#OP_WRITE}. </p>
*
* @return The valid-operation set
*/
public final int validOps() {
return SelectionKey.OP_WRITE;
} } /**
* Initializes a new instance of this class.
*/
protected Pipe() { } /**
* Returns this pipe's source channel. </p>
*
* @return This pipe's source channel
*/
public abstract SourceChannel source(); /**
* Returns this pipe's sink channel. </p>
*
* @return This pipe's sink channel
*/
public abstract SinkChannel sink(); /**
* Opens a pipe.
*
* <p> The new pipe is created by invoking the {@link
* java.nio.channels.spi.SelectorProvider#openPipe openPipe} method of the
* system-wide default {@link java.nio.channels.spi.SelectorProvider}
* object. </p>
*
* @return A new pipe
*
* @throws IOException
* If an I/O error occurs
*/
public static Pipe open() throws IOException {
return SelectorProvider.provider().openPipe();
} }
Pipe实例是通过调用不带参数的Pipe.open( )工厂方法来创建的。Pipe类定义了两个嵌套的通道类来实现管路。这两个类是Pipe.SourceChannel(管道负责读的一端)和Pipe.SinkChannel(管道负责写的一端)。这两个通道实例是在Pipe对象创建的同时被创建的,可以通过在Pipe对象上分别调用source( )和sink( )方法来取回。
此时,您可能在想管道到底有什么作用。您不能使用Pipe在操作系统级的进程间建立一个类Unix管道(您可以使用SocketChannel来建立)。Pipe的source通道和sink通道提供类似java.io.PipedInputStream和java.io.PipedOutputStream所提供的功能,不过它们可以执行全部的通道语义。请注意,SinkChannel和SourceChannel都继承了AbstractSelectableChannel(所以也间接地继承了SelectableChannel),这意味着pipe通道可以同选择器一起使用 。
管道可以被用来仅在同一个Java虚拟机内部传输数据。虽然有更加有效率的方式来在线程之间传输数据,但是使用管道的好处在于封装性。生产者线程和用户线程都能被写道通用的Channel API中。根据给定的通道类型,相同的代码可以被用来写数据到一个文件、socket或管道。选择器可以被用来检查管道上的数据可用性,如同在socket通道上使用那样地简单。这样就可以允许单个用户线程使用一个Selector来从多个通道有效地收集数据,并可任意结合网络连接或本地工作线程使用。因此,这些对于可伸缩性、冗余度以及可复用性来说无疑都是意义重大的。
Pipes的另一个有用之处是可以用来辅助测试。一个单元测试框架可以将某个待测试的类连接到管道的“写”端并检查管道的“读”端出来的数据。它也可以将被测试的类置于通道的“读”端并将受控的测试数据写进其中。两种场景对于回归测试都是很有帮助的。
管路所能承载的数据量是依赖实现的(implementation-dependent)。唯一可保证的是写到SinkChannel中的字节都能按照同样的顺序在SourceChannel上重现。
例3-11诠释了如何使用管道。
/**
*
*/
package test.nio.pipe; import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.Pipe;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Random; /**
* * Test Pipe objects using a worker thread. ** Created April, 2002 * @author
* Ron Hitchens (ron@ronsoft.com)
*/
public class PipeTest {
public static void main(String[] argv) throws Exception {
// Wrap a channel around stdout
WritableByteChannel out = Channels.newChannel(System.out);
// Start worker and get read end of channel
ReadableByteChannel workerChannel = startWorker(10);
ByteBuffer buffer = ByteBuffer.allocate(100);
while (workerChannel.read(buffer) >= 0) {
buffer.flip();
out.write(buffer);
buffer.clear();
}
} // This method could return a SocketChannel or
// FileChannel instance just as easily
private static ReadableByteChannel startWorker(int reps) throws Exception {
Pipe pipe = Pipe.open();
Worker worker = new Worker(pipe.sink(), reps);
worker.start();
return (pipe.source());
}// ----------------------------------------------------------------- /**
* * A worker thread object which writes data down a channel. * Note: this
* object knows nothing about Pipe, uses only a * generic
* WritableByteChannel.
*/
private static class Worker extends Thread {
WritableByteChannel channel;
private int reps; Worker(WritableByteChannel channel, int reps) {
this.channel = channel;
this.reps = reps;
} // Thread execution begins here
public void run() {
ByteBuffer buffer = ByteBuffer.allocate(100);
try {
for (int i = 0; i < this.reps; i++) {
doSomeWork(buffer);
// channel may not take it all at once
while (channel.write(buffer) > 0) {
// empty
}
}
this.channel.close();
} catch (Exception e) {
// easy way out; this is demo code
e.printStackTrace();
}
} private String[] products = { "No good deed goes unpunished",
"To be, or what?", "No matter where you go, there you are",
"Just say \"Yo\"", "My karma ran over my dogma" };
private Random rand = new Random(); private void doSomeWork(ByteBuffer buffer) {
int product = rand.nextInt(products.length);
buffer.clear();
buffer.put(products[product].getBytes());
buffer.put("\r\n".getBytes());
buffer.flip();
}
}
}
例3-11 工作线程对一个管道进行写操作
以上内容出自 : NIO 一书
管道Pipe的更多相关文章
- Linux简单程序实例(GNU工具链,进程,线程,无名管道pipe,基于fd的文件操作,信号,scoket)
一, GNU工具链简介: (1)编译代码步骤: 预处理 -> 编译 -> 汇编 -> 链接: 预处理:去掉注释,进行宏替换,头文件包含等工作: gcc -E test.c -o te ...
- 【IPC第二个进程间通信】管道Pipe
IPC进程间通信+管道Pipe IPC(Inter-Process Communication,进程间通信). 管道用于进程间共享数据,事实上质是共享内存 ...
- (转)Windows管道(Pipe)重定向stdout,stderr,stdin
参考: http://qiusuoge.com/11496.html http://www.cnblogs.com/BoyXiao/archive/2011/01/01/1923828.html st ...
- Java-NIO(九):管道 (Pipe)
Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 代码使用示例: @Test public vo ...
- [转]Angular2 使用管道Pipe以及自定义管道格式数据
本文转自:https://www.pocketdigi.com/20170209/1563.html 管道(Pipe)可以根据开发者的意愿将数据格式化,还可以多个管道串联. 纯管道(Pure Pipe ...
- Java NIO -- 管道 (Pipe)
Java NIO 管道是2个线程之间的单向数据连接. Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 举个例子: package com.soyo ...
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...
- 【IPC进程间通讯之二】管道Pipe
IPC进程间通信+管道Pipe IPC(Inter-Process Communication.进程间通信). 管道用于进程间共享数据,事实上质是共享内存 ...
- NIO之管道 (Pipe)
Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 代码使用示例: public static v ...
随机推荐
- php学习笔记7--php中的数组
php中的数组 1.数组的定义:显式方式:$arr = array(1,2,3,4,5); $arr1 = array('name'=>'dqrcsc','age'=>'24');隐式方式 ...
- 十六、Android 滑动效果汇总
Android 滑动效果入门篇(一)—— ViewFlipper Android 滑动效果入门篇(二)—— Gallery Android 滑动效果基础篇(三)—— Gallery仿图像集浏览 And ...
- Part 10 AngularJS sort rows by table header
Here is what we want to do 1. The data should be sorted when the table column header is clicked 2. T ...
- Android渲染机制和丢帧分析
http://blog.csdn.net/bd_zengxinxin/article/details/52525781 自己编写App的时候,有时会感觉界面卡顿,尤其是自定义View的时候,大多数是因 ...
- oledb 操作 excel
oledb excel http://wenku.baidu.com/search?word=oledb%20excel&ie=utf-8&lm=0&od=0 [Asp.net ...
- javaScript中的数组迭代方法
ECMAScript5为数组定义了5个迭代方法. 每个方法都接收两个参数:要在每一项上运行的函数 和 (可选的)运行该函数的作用域对象. 传入这些方法中的函数会接收三个参数:数组项的值,该项在数组 ...
- git使用小结
本篇文章主要介绍自己在平时工作中使用git的一些常用命令,之前都是记录在本子上面,现在把他们记录在博客上,便于保存和回顾. 1. 建立自己的git仓库 1.1 在一个新建的repo文件夹里面,执行gi ...
- curl raise 信号出core
在使用c++多线程使用libcurl抓取网页时,遇到程序随机core掉的情况,gdb 一下出错信息有这么一条:longjmp causes uninitialized stack frame. 在网上 ...
- 利用rsyslog 对linux 操作进行审计
环境:客户端和服务端都需要安装rsyslog服务 rsyslog server端 cd /etc/rsyslog.d/ cat server.conf $ModLoad imtcp $InputTC ...
- <Linux下FTP服务的搭建>
默认安装好ftp软件包匿名用户是可以下载的.匿名以后可以上传:anon_upload_enable=YES# getsebool -a | grep ftpallow_ftpd_anon_write ...