Java menyokong tiga model pengaturcaraan rangkaian: BIO, NIO, AIO
Ringkasnya, NIO boleh mengendalikan berbilang permintaan dengan satu urutan.
BIO memproses data dalam aliran, manakala NIO memproses data dalam blok I/O lebih cekap daripada aliran I /O adalah jauh lebih tinggi; dan NIO beroperasi berdasarkan Saluran dan Data sentiasa dibaca dari saluran ke penimbal, atau ditulis dari penimbal ke saluran. Pemilih digunakan untuk memantau berbilang acara saluran (seperti permintaan sambungan, ketibaan data, dll.), jadi satu rangkaian boleh memantau berbilang saluran pelanggan.
Penimbal pada dasarnya ialah blok memori yang boleh membaca dan menulis data Ia boleh difahami sebagai objek bekas (termasuk tatasusunan). set kaedah untuk membuat kerja dengan blok memori lebih mudah, dan objek penimbal mempunyai mekanisme terbina dalam untuk menjejak dan merekodkan perubahan keadaan penimbal. Saluran menyediakan saluran untuk membaca data daripada fail dan rangkaian, tetapi data yang dibaca atau ditulis mesti melalui Penampan.
Dalam NIO, Buffer ialah kelas induk peringkat atas, iaitu kelas abstrak.
ByteBuffer, menyimpan data bait ke dalam penimbal;
ShortBuffer, menyimpan data rentetan ke dalam penimbal;2
tanda: tanda
(1) Saluran NIO serupa dengan saluran
Boleh dibaca dan ditulis serentak masa, manakala strim hanya boleh membaca atau menulis;
Saluran boleh membaca dan menulis data secara tidak segerak
Saluran boleh membaca dan menulis data daripada Penampan ke membaca data, anda juga boleh menulis data ke penimbal(3) Saluran ialah antara muka dalam NIO
(4) Kelas Saluran yang biasa digunakan termasuk: FileChannel, DatagramChannel, ServerSocketChannel dan SocketChannel. ServerSocketChanne serupa dengan ServerSocket, dan SocketChannel serupa dengan Socket.FileChannel digunakan terutamanya untuk menjalankan operasi IO pada fail tempatan ialah:
baca , baca data daripada saluran dan masukkannya ke dalam penimbal
tulis, tulis data dalam penimbal ke dalam saluran
ByteBuffer menyokong taip put dan get, put put Apakah jenis data itu , get harus menggunakan jenis data yang sepadan untuk mendapatkannya, jika tidak, mungkin terdapat pengecualian BufferUnderflowException.
Boleh menukar Penampan biasa menjadi Penampan baca sahaja.
NIO juga menyediakan MappedByteBuffer, yang membenarkan fail diubah suai terus dalam ingatan (memori di luar timbunan), dan cara menyegerakkan ke fail diselesaikan oleh NIO.
NIO juga menyokong operasi membaca dan menulis melalui berbilang Penampan (iaitu tatasusunan Penampan), iaitu Penyebaran dan Pengumpulan.
Java’s NIO , menggunakan. mod IO tidak menyekat. Anda boleh menggunakan satu utas untuk mengendalikan berbilang sambungan pelanggan, dan anda akan menggunakan Pemilih.
Pemilih boleh mengesan sama ada sesuatu peristiwa berlaku pada berbilang saluran berdaftar Jika sesuatu peristiwa berlaku, ia akan memperoleh acara itu dan memproses setiap acara dengan sewajarnya. Dengan cara ini, hanya satu urutan boleh digunakan untuk mengurus berbilang saluran, iaitu, untuk mengurus berbilang sambungan dan permintaan.
Membaca dan menulis hanya akan berlaku apabila terdapat acara baca dan tulis sebenar pada sambungan/saluran, yang mengurangkan overhed sistem dan menghapuskan keperluan untuk mencipta urutan untuk setiap sambungan No perlu mengekalkan beberapa benang.
Mengelakkan overhed yang disebabkan oleh penukaran konteks antara berbilang urutan.
buka();//Dapatkan objek pemilih
pilih(masa tamat lama);//Pantau semua saluran yang didaftarkan apabila operasi IO boleh dilakukan, tambahkan SelectionKey yang sepadan pada koleksi dalaman dan kembalikan parameter tersebut untuk menetapkan masa tamat >
package com.nezha.guor.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.Iterator;public class NioServer { private Selector selector; private ServerSocketChannel serverSocketChannel; private static final int PORT = 8080; public NioServer() { try { //获得选择器 selector = Selector.open(); serverSocketChannel = ServerSocketChannel.open(); //绑定端口 serverSocketChannel.socket().bind(new InetSocketAddress(PORT)); //设置非阻塞模式 serverSocketChannel.configureBlocking(false); //将该ServerSocketChannel 注册到selector serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); }catch (IOException e) { System.out.println("NioServer error:"+e.getMessage()); } } public void listen() { System.out.println("监听线程启动: " + Thread.currentThread().getName()); try { while (true) { int count = selector.select(); if(count > 0) { //遍历得到selectionKey集合 Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if(key.isAcceptable()) { SocketChannel sc = serverSocketChannel.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); System.out.println(sc.getRemoteAddress() + " 上线 "); } //通道发送read事件,即通道是可读的状态 if(key.isReadable()) { getDataFromChannel(key); } //当前的key 删除,防止重复处理 iterator.remove(); } } else { System.out.println("等待中"); } } }catch (Exception e) { System.out.println("listen error:"+e.getMessage()); } } private void getDataFromChannel(SelectionKey key) { SocketChannel channel = null; try { channel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int count = channel.read(buffer); //根据count的值做处理 if(count > 0) { String msg = new String(buffer.array()); System.out.println("来自客户端: " + msg); //向其它的客户端转发消息(排除自己) sendInfoToOtherClients(msg, channel); } }catch (IOException e) { try { System.out.println(channel.getRemoteAddress() + " 离线了"); //取消注册 key.cancel(); }catch (IOException ex) { System.out.println("getDataFromChannel error:"+ex.getMessage()); } }finally { try { channel.close(); }catch (IOException ex) { System.out.println("channel.close() error:"+ex.getMessage()); } } } //转发消息给其它客户(通道) private void sendInfoToOtherClients(String msg, SocketChannel self ) throws IOException{ System.out.println("服务器转发消息中..."); System.out.println("服务器转发数据给客户端线程: " + Thread.currentThread().getName()); //遍历 所有注册到selector 上的 SocketChannel,并排除 self for(SelectionKey key: selector.keys()) { Channel targetChannel = key.channel(); //排除自己 if(targetChannel instanceof SocketChannel && targetChannel != self) { SocketChannel dest = (SocketChannel)targetChannel; //将信息存储到buffer ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes()); //将buffer数据写入通道 dest.write(buffer); } } } public static void main(String[] args) { //创建服务器对象 NioServer nioServer = new NioServer(); nioServer.listen(); }}
Atas ialah kandungan terperinci Menganalisis penggunaan dan ciri contoh Java NIO. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!