Pipe.SinkChannel和Pipe.SourceChannel类的使用
Pipe.SinkChannel类标识Pipe的可写入结尾的通道:
Pipe.SourceChannel类标识Pipe的可读取结尾的通道:
创建Pipe.SinkChannel和Pipe.SourceChannel类的实例需要使用Pipe类。
管道由一对通道组成
:一个可写人的sink通道和一个可读取的source通道。一旦将某些字节写人接收器通道,就可以按照与写人时完全相同的顺序从源通道中读取这些字节。
在另一个线程从管道中读取这些字节或先前已写人的字节之前,是否阻塞将该字节写人管道的线程是与系统相关的,因此是未指定的。很多管道实现都对接收器和源通道之间一定数量的字节进行缓冲,但是不应假定会进行这种缓冲。
public static void main(String[] args) {
try {
Pipe pipe = Pipe.open();
Pipe.SinkChannel sinkChannel = pipe.sink();
Pipe.SourceChannel sourceChannel = pipe.source();
Thread t1 = new Thread(){
@Override
public void run() {
try {
Thread.sleep(1024);
for (int i = 0; i < 5; i++) {
sinkChannel.write(ByteBuffer.wrap(("我来自客户端A " + (i + 1) + "\r\n").getBytes()));
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t1.start();
Thread t2 = new Thread(){
@Override
public void run() {
try {
Thread.sleep(1024);
for (int i = 0; i < 5; i++) {
sinkChannel.write(ByteBuffer.wrap(("我来自客户端B " + (i + 1) + "\r\n").getBytes()));
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
t2.start();
Thread.sleep(3000);
sinkChannel.close();
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int readLength = sourceChannel.read(readBuffer);
while (readLength != -1) {
System.out.println(new String(readBuffer.array(), 0, readLength));
readLength = sourceChannel.read(readBuffer);
}
sourceChannel.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
我来自客户端A 1
我来自客户端A 2
我来自客户端B 1
我来自客户端B 2
我来自客户端B 3
我来自客户端A 3
我来自客户端B 4
我来自客户端A 4
我来自客户端B 5
我来自客户端A 5
SelectorProvider类的使用
SelectorProvider是用于选择器和可选择通道的服务提供者类。选择器提供者实现类是SelectorProvider类的一个子类,它具有零参数的构造方法,并实现了以下指定的抽象方法。给定的对Java虚拟机的调用维护了单个系统级的默认提供者实例,它由provider()方法返回。
第一次调用该方法将查找指定的默认提供者。系统级的默认提供者由DatagramChannel、Pipe 、Selector 、ServerSocketChannel 和SocketChannel类的静态open()方法使用。System.inheritedChannel)方法也使用它。除了默认提供者之外,程序还可以使用其他提供者,方法是通过实例化一个提供者,然后直接调用此类中定义的open()方法。
多个并发线程可安全地使用SelectorProvider类中的所有方法。
public static void main(String[] args) throws IOException {
SelectorProvider provider = SelectorProvider.provider();
System.out.println("provider=" + provider.getClass().getName());
Selector selector = provider.openSelector();
DatagramChannel datagramChannel1 = provider.openDatagramChannel();
DatagramChannel datagramChannel2 = provider.openDatagramChannel(StandardProtocolFamily.INET);
DatagramChannel datagramChannel3 = provider.openDatagramChannel(StandardProtocolFamily.INET6);
Pipe pipe = provider.openPipe();
ServerSocketChannel serverSocketChannel = provider.openServerSocketChannel();
SocketChannel socketChannel = provider.openSocketChannel();
//方法inheritedChannel()在源代码中返回的值就是null
Channel channel = provider.inheritedChannel();
System.out.println("openSelector()=" + selector.getClass().getName());
System.out.println("openDatagramChannel()=" + datagramChannel1.getClass().getName());
System.out.println("openDatagramChannel(StandardProtocalFamily.INET)=" + datagramChannel2.getClass().getName());
System.out.println("openPipe()=" + pipe.getClass().getName());
System.out.println("openServerSocketChannel()=" + socketChannel.getClass().getName());
System.out.println("openSocketChannel()=" + socketChannel.getClass().getName());
System.out.println("inheritedChannel()=" + channel);
}
provider=sun.nio.ch.KQueueSelectorProvider
openSelector()=sun.nio.ch.KQueueSelectorImpl
openDatagramChannel()=sun.nio.ch.DatagramChannelImpl
openDatagramChannel(StandardProtocalFamily.INET)=sun.nio.ch.DatagramChannelImpl
openPipe()=sun.nio.ch.PipeImpl
openServerSocketChannel()=sun.nio.ch.SocketChannelImpl
openSocketChannel()=sun.nio.ch.SocketChannelImpl
inheritedChannel()=null