当前位置 : 主页 > 编程语言 > java >

Java NIO 必知必会(Example)

来源:互联网 收集:自由互联 发布时间:2022-08-10
管道流: Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。 1 package base.nio.threaddemo; 2 3 import java.io.IOException; 4 i

管道流:

Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。

 

Java NIO 必知必会(Example)_java

 

1 package base.nio.threaddemo;
2
3 import java.io.IOException;
4 import java.nio.ByteBuffer;
5 import java.nio.channels.Pipe;
6
7 /**
8 * @program: Lear-Java
9 * @description:
10 * @author: Mr.Dai
11 * @create: 2018-10-05 20:43
12 **/
13 public class ThreadSend {
14
15 private Pipe pipe;
16
17
18 private void init() throws Exception {
19 this.pipe = Pipe.open();
20 }
21
22
23 class SendInner1 extends Thread {
24
25 @Override
26 public void run() {
27 // 单向流 发送数据
28 try {
29 Pipe.SinkChannel sink = pipe.sink();
30 sink.configureBlocking(false);
31
32 while (true) {
33 if (sink.isOpen()) {
34 sink.write(ByteBuffer.wrap("abcd".getBytes()));
35 }
36 Thread.sleep(1000);
37 }
38 } catch (InterruptedException | IOException e) {
39 e.printStackTrace();
40 }
41 }
42 }
43
44 class ReverInner extends Thread {
45 @Override
46 public void run() {
47 try {
48 // 单向流 拿到数据
49 Pipe.SourceChannel source = pipe.source();
50
51 source.configureBlocking(false);
52
53 while (true) {
54 if (source.isOpen()) {
55 ByteBuffer buffer = ByteBuffer.allocate(10);
56 buffer.clear();
57 source.read(buffer);
58 // 这里必须去掉 trim
59 if(new String(buffer.array()).trim().equals("")){
60 continue;
61 }
62 System.out.println(new String(buffer.array()).trim());
63 }
64 Thread.sleep(1000);
65 }
66 } catch (InterruptedException | IOException e) {
67 e.printStackTrace();
68 }
69 }
70 }
71
72 public static void main(String[] args) throws Exception {
73 ThreadSend send = new ThreadSend();
74
75 send.init();
76
77 SendInner1 sendI = send.new SendInner1();
78
79 ReverInner revI = send.new ReverInner();
80
81 sendI.start();
82 revI.start();
83 }
84
85
86

 

套接字通道流

 

非阻塞模式

ServerSocketChannel可以设置成非阻塞模式。在非阻塞模式下,accept() 方法会立刻返回,如果还没有新进来的连接,返回的将是null。 因此,需要检查返回的SocketChannel是否是null。如:

1 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
2
3 serverSocketChannel.socket().bind(new InetSocketAddress(9999));
4 serverSocketChannel.configureBlocking(false);
5
6 while(true){
7 SocketChannel socketChannel =
8 serverSocketChannel.accept();
9
10 if(socketChannel != null){
11 //do something with socketChannel...
12 }
13

 

server:

1 package base.nio.chatdemo;
2
3
4 import java.net.InetSocketAddress;
5 import java.nio.ByteBuffer;
6 import java.nio.channels.SelectionKey;
7 import java.nio.channels.Selector;
8 import java.nio.channels.ServerSocketChannel;
9 import java.nio.channels.SocketChannel;
10 import java.util.Iterator;
11 import java.util.Set;
12
13 /**
14 * @program: Lear-Java
15 * @description: Nio 聊天服务端
16 * @author: Mr.Dai
17 * @create: 2018-10-05 16:31
18 **/
19 public class ChatServer {
20
21 /**
22 * 通道管理器
23 */
24 private Selector selector;
25
26 private void initServer(int port) throws Exception{
27
28 ServerSocketChannel serverChannel = ServerSocketChannel.open();
29
30 serverChannel .socket().bind(new InetSocketAddress(port));
31 // 配置非阻塞
32 serverChannel .configureBlocking(false);
33
34
35 this.selector=Selector.open();
36
37 /**
38 * 将通道管理器和该通道绑定,并为该通道注册selectionKey.OP_ACCEPT事件
39 * 注册该事件后,当事件到达的时候,selector.select()会返回,
40 * 如果事件没有到达selector.select()会一直阻塞
41 * selector.selectNow() 立即返回 无论是否准备好 可能返回0
42 */
43 serverChannel .register(this.selector, SelectionKey.OP_ACCEPT);
44
45 }
46
47 /**
48 * 采用轮训的方式监听selector上是否有需要处理的事件,如果有,进行处理
49 */
50 public void listen() throws Exception {
51 System.out.println("start------------------->");
52 while (true){
53 // 在没有注册事件来到时 将会一直阻塞
54 selector.select();
55 Set<SelectionKey> set = selector.selectedKeys();
56 Iterator<SelectionKey> iterator = set.iterator();
57
58 while (iterator.hasNext()){
59 SelectionKey key = iterator.next();
60 // 移除当前阻塞队列
61 iterator.remove();
62 if(key.isAcceptable()){
63 ServerSocketChannel server = (ServerSocketChannel) key.channel();
64
65 SocketChannel channel = server.accept();
66 channel.configureBlocking(false);
67 // 服务端发送数据
68 channel.write(ByteBuffer.wrap(new String("hello client").getBytes()));
69 // 在客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限
70 channel.register(this.selector,SelectionKey.OP_READ);
71
72 }else if(key.isReadable()){
73 SocketChannel channel = (SocketChannel) key.channel();
74
75 ByteBuffer buffer = ByteBuffer.allocate(10);
76 channel.read(buffer);
77
78 String msg = new String(buffer.array()).trim();
79
80 System.out.println("客户端发送过来的讯息:"+msg);
81 // 在读取后 将柱塞队列数据 改变监听为Accept
82 ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());
83 channel.write(outBuffer);
84 }
85 }
86 }
87
88 }
89
90 public static void main(String[] args) throws Exception{
91 ChatServer server = new ChatServer();
92 server.initServer(8989);
93 server.listen();
94 }
95
96

clien:

1 package base.nio.chatdemo;
2
3 import java.io.IOException;
4 import java.net.InetSocketAddress;
5 import java.nio.ByteBuffer;
6 import java.nio.channels.SelectionKey;
7 import java.nio.channels.Selector;
8 import java.nio.channels.SocketChannel;
9 import java.util.Iterator;
10
11 /**
12 * @program: Lear-Java
13 * @description: nio 聊天客户端
14 * @author: Mr.Dai
15 * @create: 2018-10-05 16:31
16 **/
17 public class ChatClient {
18
19
20 /**
21 * 提供柱阻塞队列 管理器
22 */
23 private Selector selector;
24
25
26 private void ininCliect(String ip,int port) throws Exception{
27
28 SocketChannel channel = SocketChannel.open();
29
30 channel .connect(new InetSocketAddress(ip,port));
31
32 this.selector=Selector.open();
33
34 channel .configureBlocking(false);
35
36
37 channel .register(this.selector, SelectionKey.OP_CONNECT);
38
39 }
40
41 public void listen() throws Exception {
42
43 while (true){
44
45 selector.select();
46
47 Iterator<SelectionKey> ite = selector.selectedKeys().iterator();
48
49 while (ite.hasNext()){
50 SelectionKey key = ite .next();
51 ite .remove();
52 if(key.isConnectable()){
53 SocketChannel channel = (SocketChannel) key.channel();
54 // 是否准备好连接
55 if(channel.isConnectionPending()){
56 channel.finishConnect();
57 }
58 channel.configureBlocking(false);
59 // 向server 发送数据
60 channel.write(ByteBuffer.wrap("向server 发送数据".getBytes()));
61
62 channel.register(selector,SelectionKey.OP_READ);
63
64 }else if(key.isReadable()){
65 m1(key);
66 }
67 }
68 }
69 }
70
71 private void m1(SelectionKey key) throws IOException {
72 SocketChannel channel = (SocketChannel) key.channel();
73
74 ByteBuffer buffer = ByteBuffer.allocate(10);
75 channel.read(buffer);
76 System.out.println("服务端的消息为:"+new String(buffer.array()));
77
78 ByteBuffer outBuffer = ByteBuffer.wrap(new String("aaa").getBytes());
79 channel.write(outBuffer);
80 }
81
82 public static void main(String[] args) throws Exception {
83 ChatClient client = new ChatClient();
84
85 client.ininCliect("127.0.0.1",8989);
86 client.listen();
87 }
88
89

 



上一篇:Java中对象拷贝的两种方式
下一篇:没有了
网友评论