Rumah >Java >javaTutorial >Membawa anda untuk menguasai sepenuhnya Java NIO (perkongsian ringkasan)
Artikel ini membawa anda pengetahuan yang berkaitan tentang java, yang terutamanya memperkenalkan isu berkaitan NIO, termasuk teras NIO, perbandingan antara BIO dan NIO, dan pelaksanaan pelanggan pelayan mudah melalui komunikasi Terminal NIO, saya harap ia akan membantu semua orang.
Disyorkan kajian: "tutorial java"
Intipati model I/O ialah saluran yang digunakan untuk menghantar dan menerima data, yang sebahagian besarnya menentukan prestasi komunikasi program.
Java menyokong tiga model pengaturcaraan rangkaian: BIO, NIO, AIO
BIO: penyegerakan dan penyekatan, mod pelaksanaan perkhidmatan ialah satu sambungan dan satu utas, iaitu, pelanggan mempunyai satu sambungan Apabila membuat permintaan, pelayan perlu memulakan benang untuk pemprosesan.
NIO: Segerak dan tidak menyekat, mod pelaksanaan pelayan ialah benang memproses sambungan permintaan berbilang, iaitu permintaan yang dihantar oleh pelanggan akan didaftarkan kepada pemultipleks dan dimultiplekskan Pelayan meninjau sambungan dan memprosesnya jika terdapat permintaan I/O.
AIO: Asynchronous non-blocking, AIO memperkenalkan konsep saluran tak segerak, menggunakan mod Proactor, memudahkan penulisan program dan hanya memulakan urutan selepas permintaan yang sah terlebih dahulu Beritahu pelayan selepas selesai.
Kaedah BIO sesuai untuk seni bina dengan bilangan sambungan yang agak kecil dan tetap. Kaedah ini sesuai untuk Keperluan sumber pelayan agak tinggi, dan concurrency terhad kepada aplikasi Ia adalah satu-satunya pilihan sebelum JDK1.4, tetapi program ini mudah dan mudah difahami.
Kaedah NIO sesuai untuk seni bina dengan bilangan sambungan yang banyak dan sambungan yang agak pendek (operasi ringan), seperti pelayan sembang, sistem barraj, komunikasi antara pelayan, dsb. Pengaturcaraan adalah lebih rumit, dan JDK1.4 mula menyokongnya.
Kaedah AIO digunakan dalam seni bina dengan bilangan sambungan yang besar dan sambungan yang agak panjang (operasi berat), seperti pelayan album foto memanggil OS sepenuhnya untuk mengambil bahagian dalam operasi serentak . Pengaturcaraan agak rumit, dan JDK7 mula menyokongnya
Pelayan memulakan ServerSocket
Pelanggan memulakan Soket Untuk berkomunikasi dengan pelayan, secara lalai pelayan perlu mewujudkan urutan untuk setiap pelanggan untuk berkomunikasi dengannya; >Selepas pelanggan menghantar permintaan, ia terlebih dahulu merujuk pelayan sama ada terdapat tindak balas thread, jika tidak Ia akan menunggu atau ditolak; akan menunggu permintaan untuk tamat sebelum meneruskan pelaksanaan;
5 , teras NIO
HTTP2.0 menggunakan teknologi pemultipleksan untuk membenarkan sambungan yang sama memproses berbilang permintaan secara serentak, dan bilangan permintaan serentak adalah beberapa susunan magnitud yang lebih besar daripada HTTP1.1.
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.
Penerangan carta alir:
Pemilih yang sepadan Satu utas, satu utas sepadan dengan berbilang saluran (sambungan);
Data dibaca dan ditulis melalui Buffer, yang sama dengan BIO ialah sama ada aliran input atau aliran keluaran, yang tidak boleh dwiarah, tetapi Penampan NIO boleh dibaca atau ditulis dan memerlukan flip. kaedah untuk menukar
saluran adalah dwiarah dan boleh mengembalikan status sistem pengendalian asas Sebagai contoh, Linux, saluran sistem pengendalian asas adalah dua hala; Penampan (buffer)
1. Senarai subkelas Penimbal yang biasa digunakan
pulangan penimbal akhir awam( )//Pulihkan penimbal ini
boolean abstrak awam isReadOnly();//Memaklumkan sama ada penimbal ini hanya Baca penimbal
FileChannel digunakan terutamanya untuk melaksanakan operasi IO pada fail tempatan ialah:
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(); }}</selectionkey>
package com.nezha.guor.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.Scanner;public class NioClient { private final int PORT = 8080; //服务器端口 private Selector selector; private SocketChannel socketChannel; private String username; public NioClient() throws IOException { selector = Selector.open(); socketChannel = socketChannel.open(new InetSocketAddress("127.0.0.1", PORT)); //设置非阻塞 socketChannel.configureBlocking(false); //将channel注册到selector socketChannel.register(selector, SelectionKey.OP_READ); username = socketChannel.getLocalAddress().toString().substring(1); System.out.println(username + " is ok..."); } //向服务器发送消息 public void sendInfo(String info) { info = username + " 说:" + info; try { socketChannel.write(ByteBuffer.wrap(info.getBytes())); }catch (IOException e) { System.out.println("sendInfo error:"+e.getMessage()); } } //读取从服务器端回复的消息 public void readInfo() { try { int readChannels = selector.select(); if(readChannels > 0) { Iterator<selectionkey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if(key.isReadable()) { //得到相关的通道 SocketChannel sc = (SocketChannel) key.channel(); //得到一个Buffer ByteBuffer buffer = ByteBuffer.allocate(1024); //读取 sc.read(buffer); //把读到的缓冲区的数据转成字符串 String msg = new String(buffer.array()); System.out.println(msg.trim()); } } iterator.remove(); //删除当前的selectionKey, 防止重复操作 } else { System.out.println("没有可以用的通道..."); } }catch (Exception e) { System.out.println("readInfo error:"+e.getMessage()); } } public static void main(String[] args) throws Exception { NioClient nioClient = new NioClient(); new Thread() { public void run() { while (true) { nioClient.readInfo(); try { Thread.currentThread().sleep(2000); }catch (InterruptedException e) { System.out.println("sleep error:"+e.getMessage()); } } } }.start(); //发送数据给服务器端 Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { nioClient.sendInfo(scanner.nextLine()); } }}</selectionkey>
Pembelajaran yang disyorkan: "tutorial java
Atas ialah kandungan terperinci Membawa anda untuk menguasai sepenuhnya Java NIO (perkongsian ringkasan). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!