Rumah  >  Artikel  >  Java  >  Menganalisis penggunaan dan ciri contoh Java NIO

Menganalisis penggunaan dan ciri contoh Java NIO

王林
王林ke hadapan
2023-05-06 22:25:06847semak imbas

Menganalisis penggunaan dan ciri contoh Java NIO


1. Peta minda Java

Menganalisis penggunaan dan ciri contoh Java NIO

2

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 untuk permintaan I/O dan memprosesnya.

  • AIO: Asynchronous non-blocking, AIO memperkenalkan konsep saluran tak segerak, menggunakan mod Proactor, memudahkan penulisan program dan hanya memulakan urutan selepas permintaan yang sah pertama Maklumkan pelayan selepas selesai.

3. Senario aplikasi BIO, NIO, AIO

  • 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

4 Proses pengaturcaraan BIO yang mudah

  • 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

    NIO mempunyai tiga bahagian teras: Pemilih (pemilih), Saluran (saluran) dan Penampan (buffer).
  • NIO berorientasikan penimbal, atau pengaturcaraan berorientasikan blok Data dibaca ke dalam penimbal yang diproses kemudiannya Ia menyediakan rangkaian yang tidak menyekat dan berskala tinggi.
  • 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.

  • 6. Perbandingan antara BIO dan NIO

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.


7. Gambarajah skematik tiga prinsip teras NIO

  • Penerangan carta alir:

  • Pemilih yang sepadan Satu utas, satu utas sepadan dengan berbilang saluran (sambungan);

    Setiap saluran akan sepadan dengan Penampan;
  • Saluran yang mana program beralih ditentukan oleh acara dan Acara ialah konsep penting;
Pemilih akan menghidupkan setiap saluran mengikut acara yang berbeza;

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 beralih;

8. Penampan

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.

1. Senarai subkelas Penimbal yang biasa digunakan

  • ByteBuffer, menyimpan data bait ke dalam penimbal;

    ShortBuffer, menyimpan data rentetan ke dalam penimbal;
  • CharBuffer, menyimpan data aksara ke dalam penimbal; ke penimbal;
  • LongBuffer, menyimpan data integer panjang ke dalam penimbal; 🎜>
  • FloatBuffer, menyimpan perpuluhan dalam penimbal;

  • 2

    tanda: tanda
  • kedudukan: kedudukan, indeks elemen seterusnya untuk dibaca atau ditulis, nilai akan ditukar setiap kali data penimbal dibaca atau ditulis, seperti berikut Persediaan membaca dan menulis.
  • had: Menunjukkan titik akhir semasa penimbal tidak boleh dilakukan pada lokasi penimbal melebihi had. Dan had boleh diubah suai

kapasiti: kapasiti, iaitu jumlah maksimum data yang boleh ditampung ia ditetapkan apabila penimbal dibuat dan tidak boleh diubah.

  • 3. Api penimbal biasa

  • Api yang diperkenalkan dalam JDK1.4
  • kapasiti int akhir awam( )//Mengembalikan kapasiti penimbal ini
  • kedudukan int akhir awam( )//Mengembalikan kedudukan penimbal ini

Menganalisis penggunaan dan ciri contoh Java NIO

kedudukan Penampan akhir awam (int newPositio)//Tetapkan kedudukan penimbal ini

had int akhir awam()//Kembalikan Had penimbal ini sebanyak

  • had Penampan akhir awam (int newLimit)//Tetapkan had penimbal ini

  • tanda Penampan akhir awam( )// Tetapkan tandakan pada kedudukan penimbal ini

  • set semula Penampan akhir awam( )//Tetapkan semula kedudukan penimbal ini kepada kedudukan tanda sebelumnya

  • Penimbal akhir awam clear( )//Kosongkan penimbal ini, iaitu, pulihkan setiap tanda kepada keadaan asalnya, tetapi data sebenarnya tidak dipadamkan dan operasi seterusnya akan menimpanya

  • Buffer akhir awam flip( )//Terbalikkan penimbal ini

  • pundurkan Penampan akhir awam( )//Putar balik penimbal ini

  • int akhir awam baki( )//Mengembalikan bilangan elemen antara kedudukan semasa dan had

  • boolean akhir awam hasRemaining()//Memaklumkan sama ada terdapat unsur antara kedudukan semasa dan had

  • boolean abstrak awam isReadOnly( ); // Beritahu sama ada penimbal ini ialah penimbal baca sahaja

  • API yang diperkenalkan dalam JDK1.6

  • boolean abstrak awam hasArray();//Maklumkan jika penimbal ini mempunyai tatasusunan pelaksanaan asas yang boleh diakses

  • tatasusunan Objek abstrak awam();/ / Kembalikan tatasusunan pelaksanaan asas penimbal ini

  • public abstract int arrayOffset();//Kembalikan offset elemen penimbal pertama dalam tatasusunan pelaksanaan asas penimbal ini

boolean abstrak awam isDirect();//Maklumkan sama ada penimbal ini ialah penimbal langsung

  • 9. Saluran
  • 1. Pengenalan asas
  • (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 segerakMenganalisis penggunaan dan ciri contoh Java NIO

Saluran boleh membaca dan menulis data daripada Penampan ke membaca data, anda juga boleh menulis data ke penimbal

(2) Strim dalam BIO adalah sehala, contohnya, objek FileInputStream hanya boleh membaca data, manakala strim dalam Saluran NIO adalah dua arah dan boleh dibaca atau ditulis.

(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.
    (5) FileChannel digunakan untuk membaca dan menulis data fail, DatagramChannel digunakan untuk membaca dan menulis data UDP, ServerSocketChannel dan SocketChannel digunakan untuk membaca dan menulis data TCP.
  • 2. FileChannel
  • 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


pindahDari, dari Salin data daripada saluran sasaran ke saluran semasa

transferKe, salin data daripada saluran semasa ke saluran sasaran

3. Nota dan butiran tentang Penampan dan 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.

10. Pemilih (pemilih)

1 Pengenalan asas

  • 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.

2 kaedah berkaitan pemilih

  • 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 >

  • selectedKeys();//Dapatkan semua SelectionKeys daripada koleksi dalaman.

3. Nota

Fungsi ServerSocketChannel dalam NIO adalah serupa dengan ServerSocket, dan fungsi SocketChannel adalah serupa dengan Socket.

11. Komunikasi pelayan-pelanggan yang mudah melalui NIO

1 Pelayan
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();
    }}

2 3. Output konsol

Menganalisis penggunaan dan ciri contoh Java NIO
Menganalisis penggunaan dan ciri contoh Java NIO

Atas ialah kandungan terperinci Menganalisis penggunaan dan ciri contoh Java NIO. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam