pipe 说明
管道可以被用来仅在同一个 Java 虚拟机内部传输数据。虽然有更加有效率的方式来在线程之间传输数据,但是使用管道的好处在于封装性。[1]
code
package com.nio.demo;
import java.io.IOException;
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;
public class PipeTest {
public static void main(String[] args) throws Exception {
// 创建一个可写通道,用于向控制台输出管道中的内容
WritableByteChannel out = Channels.newChannel(System.out);
//启动一个工作线程,向管道写入数据,返回值为管道读的一端
ReadableByteChannel readableByteChannel = startWorker(10);
//创建一个缓冲区,用于接收管道中的数据
ByteBuffer buffer = ByteBuffer.allocate(100);
//如果工作线程中的管道一端不关闭,这个地方会一直阻塞在这里,即使没有数据传输
while(readableByteChannel.read(buffer)>=0) {
//将缓冲区翻转成一个准备读出元素的释放状态
buffer.flip();
//输出到控制台
out.write(buffer);
//清空缓冲区
buffer.clear();
}
}
private static ReadableByteChannel startWorker(int reps) throws Exception {
//打开一个管道
Pipe pipe = Pipe.open();
//创建工作线程,并打开管道写的一端(pipe.sink())
Worker worker=new Worker(pipe.sink(), reps);
worker.start();
//返回管道读的一端
return (pipe.source());
}
//工作线程类
private static class Worker extends Thread {
WritableByteChannel channel;
private int reps;
public Worker(WritableByteChannel channel, int reps) {
this.channel = channel;
this.reps = reps;
}
@Override
public void run() {
ByteBuffer buffer = ByteBuffer.allocate(100);
try {
for (int i = 0; i < reps; i++) {
doSomeWork(buffer);
while (channel.write(buffer) > 0) {
// empty
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
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();
}
}
}
-
《Java Nio》 ↩