1. Conceptos básicos
IO es el proceso de copiar datos por memoria principal y dispositivos externos (discos duros, terminales, redes, etc.). IO es la implementación funcional subyacente del sistema operativo, que se completa a través de instrucciones de E/S.
Todos los sistemas de tiempo de ejecución de idiomas proporcionan herramientas de alto nivel para realizar E/S. (C's Printfscanf, encapsulación orientada a objetos de Java)
2. Revisión de Java Standard IO
La biblioteca de clases IO estándar de Java es una abstracción de IO orientada a objetos. Basado en la implementación subyacente de métodos locales, no necesitamos prestar atención a la implementación subyacente. InputStream/outputStream: transfiera un byte a la vez. Lector/escritor: un personaje a la vez.
3.NIO Introducción
Nio es la abreviatura de Javanewio, una nueva API proporcionada en JDK1.4. Las características que Sun afirma oficialmente son las siguientes:
Proporciona soporte de caché (búfer) para todos los tipos primitivos.
Solución de codificación y decodificación del conjunto de caracteres.
Canal: una nueva abstracción original de E/S.
Admite interfaces de acceso a archivos para archivos mapeados de bloqueo y memoria.
Proporciona E/S de red sin bloqueo, sin bloqueo y altamente escalable.
Este artículo aprenderá e introducirá estas características.
4.Buffer & Chanel
El canal y el búfer son NIO y son las dos abstracciones de tipo de datos más básicas.
Buffer:
Es un bloque continuo de memoria.
Es el lugar de tránsito para leer o escribir datos de NIO.
Canal:
La fuente de datos o destino de los datos
Una interfaz única para proporcionar datos a búferes o leer datos de búfer, objetos de búfer.
Soporte de E/S asincrónico
Ejemplo 1: copyfile.java:
muestra de paquete; import java.io.fileInputStream; import java.io.fileOutputStream; import java.nio.byteBuffer; import java.nio.channels.fileChannel; public class CopyFile {public static void main (string [] args) Excepción {string infile = "c: //copy.sql"; string outfile "; "C: //copy.txt"; // Obtenga transmisiones de entrada y salida de los archivos de origen y de destino fileInputStream fin = new FileInputStream (infile); fileOutputStream fout = new FileOutputStream (OutFile); // Obtener los canales de entrada y salida Filechannel = FIN.getChannel (); FileChannel FCout = Fout.getChannel (); buffer = bytebuffer.allocate (1024); mientras (verdadero) {// claro el método restablece el búfer para que pueda aceptar leer datos buffer.clear (); // leer datos desde el canal de entrada al búfer int r = fcin.read (buffer); // El método de lectura devuelve el número de Bytes Read, que puede ser cero, si el canal ha alcanzado la transmisión de la transmisión, devuelve -1 si (r == -1) {break;} otro canal buffer.flip (); // Escribir datos desde el canal de salida al buffer fcout.write (buffer);}}}La estructura interna del búfer es la siguiente (la siguiente figura se copia de la información):
Figura 2: Estructura interna del búfer
Un búfer controla principalmente el proceso de lectura y escritura en tres variables posición, límite y capacidad. El significado de estas tres variables se muestra en la siguiente tabla:
parámetro | Modo de escritura | Modo de lectura |
posición | El número de datos de la unidad actualmente escritos. | La ubicación de datos de la unidad actual se lee. |
límite | Representa el número máximo de unidades de datos y capacidad que se puede escribir es el mismo. | Representa el número máximo de unidades de datos que se pueden leer, lo que es consistente con la cantidad de datos de la unidad escritos antes. |
capacidad | Capacidad de amortiguación | Capacidad de amortiguación |
Métodos de búfer comunes:
flip (): Convertir el modo de escritura en modo de lectura
Rewind (): Restablecer la posición a 0, generalmente utilizada para la lectura repetida.
Clear (): Borre el búfer y prepárese para ser escrito nuevamente (la posición se convierte en 0, el límite se convierte en capacidad).
Compact (): Copie datos no leídos al cabezal del búfer.
Mark (), RESET (): Mark puede marcar una posición, el reinicio se puede restablecer a esta posición.
Tipos comunes de búfer: bytebuffer, mappedbytebuffer, charbuffer, doublebuffer, floatbuffer, intbuffer, longbuffer, shortbuffer.
Canales comunes: Filechannel, DataGramChannel (UDP), Socketchannel (TCP), Serversocketchannel (TCP)
Se realizó una prueba de rendimiento simple en esta máquina. Mi computadora portátil funciona con moderación. (Consulte el archivo adjunto para el código específico. Consulte el ejemplo a continuación en el paquete NIO.Sample.FileCopy) Los siguientes son los datos de referencia:
Escenario 1: Copie un archivo de 370m
Escenario 2: Tres hilos copian al mismo tiempo, cada hilo copia un archivo de 370 m.
Escena | FileInputStream+ FileOutputStream | FileInputStream+ BufferedInputStream+ FileOutputStream | Bytebuffer+ Filequanal | MappedByteBuffer +FileCannel |
Escena por un tiempo (milisegundos) | 25155 | 17500 | 19000 | 16500 |
Escena 2 tiempo (milisegundos) | 69000 | 67031 | 74031 | 71016 |
5.nio.charset
Codificación de caracteres y decodificación: Bytecode en sí es solo algunos números, que se analizan correctamente en el contexto correcto. Al almacenar datos en ByteBuffer, debe considerar el método de codificación del conjunto de caracteres. Al leer y mostrar los datos de Bytebuffer, implica decodificar el conjunto de caracteres.
Java.nio.charset proporciona un conjunto de soluciones para codificar y decodificar.
Tomando nuestra solicitud HTTP más común como ejemplo, la solicitud debe codificarse correctamente al solicitar. La respuesta debe decodificarse correctamente cuando se obtiene.
El siguiente código envía una solicitud a Baidu y obtiene los resultados para la visualización. El ejemplo demuestra el uso de Charset.
Ejemplo 2Baidureader.java
paquete nio.readpage; import java.nio.bytebuffer; import java.nio.channels.socketchannel; import java.nio.charset.charset; import java.net.inetsocketadaddress; import java.io.ioexception; public class Baidureader {Charset private Charset = Charset.forname ("Gbbk"; Canal Socketchannel; public void readhtmlContent () {try {inetSocketAddress Socketaddress = new InetSocketAddress ("www.baidu.com", 80); // step1: abra el canal de conexión = socketchannel.open (Sococketaddress); // step2: envíe la solicitud del canal. Http/1.1 " +"/r/n/r/n ")); // paso3: lea los datos bytebuffer buffer = bytebuffer.allocate (1024); // Cree un búfer de 1024 bytes mientras (canal.read (buffer)! = -1) {buffer.flip (); // El método de flip se llama antes de la operación de buffer. System.out.println (charset.decode (buffer)); // use charset.decode para convertir bytes en string buffer.clear (); // clear buffer}} catch (ioException e) {system.err.println (e.ToString ());} finalmente {if (canal! = NULL) {trey {cloin (); e) {}}}} public static void main (string [] args) {new Baidureader (). ReadhtmlContent ();}}6. IO sin bloqueo
Con respecto a la IO sin bloqueo, entenderemos por los aspectos de lo que está bloqueando, lo que no es bloqueo, el principio sin bloqueo y la API del núcleo asincrónico.
¿Qué es el bloqueo?
Un proceso de comunicación de red de red común es el siguiente:
De este proceso de comunicación de red, comprendamos qué es el bloqueo:
Si la conexión no ha llegado en el proceso anterior, entonces acepta Bloquear, el programa tendrá que colgar después de ejecutar aquí, y la CPU ejecutará otros hilos.
Si los datos no están listos en el proceso anterior, la lectura también bloqueará.
Características de la red de bloqueo IO: múltiples conexiones de múltiples subprocesos. Cada hilo tiene su propio espacio de pila y toma algo de tiempo de CPU. Cada hilo se bloqueará cuando encuentre una lista externa. El resultado del bloqueo es que conducirá a una gran cantidad de conmutación de contexto de proceso. Y la mayoría de los cambios de contexto de proceso pueden no tener sentido. Por ejemplo, suponga que un subproceso escucha un puerto, y solo habrá algunas solicitudes en un día, pero la CPU tiene que hacer constantemente intentos de conmutación de contexto para el hilo, y la mayor parte de la conmutación termina en el bloqueo.
¿Qué no es bloqueo?
Aquí hay una metáfora:
En un autobús de A a B, hay muchos puntos en el camino que pueden salir. El conductor no sabe qué puntos saldrán del autobús. ¿Cómo lidiar con aquellos que necesitan subir mejor al autobús?
1. Durante el proceso, el conductor regularmente le pregunta a cada pasajero si ha llegado al destino. Si alguien dice eso, el conductor se detiene y el pasajero se baja. (Similar al bloqueo)
2. Todos les dicen al vendedor de entradas su destino y luego duerme. El conductor solo interactúa con el vendedor de entradas. Cuando llegue en cierto punto, el vendedor de entradas notificará al pasajero que salga del autobús. (Similar al no bloqueo)
Obviamente, todos para llegar a un destino pueden considerarse un hilo, y el conductor puede considerarse una CPU. En el estilo de bloqueo, cada subproceso debe encuestar y cambiar constantemente el contexto para lograr el resultado de encontrar el destino. En el modo sin bloqueo, cada pasajero (hilo) está durmiendo (durmiendo) y solo se despierta cuando el entorno externo real está listo. Tal despertador definitivamente no bloqueará.
El principio de no bloquear
Cambie todo el proceso a tareas pequeñas y compléntelo a través de la colaboración entre tareas.
Un hilo dedicado maneja todos los eventos IO y es responsable de la distribución.
Mecanismo basado en eventos: se desencadena cuando llega un evento, en lugar de monitorear los eventos simultáneamente.
Comunicación de hilos: los hilos se comunican a través de Wait, Notify y otros medios. Asegúrese de que cada cambio de contexto tenga sentido. Reduzca el cambio de proceso innecesario.
La siguiente es la estructura del IO asíncrono:
El reactor es el papel metafórico anterior del vendedor de boletos. El flujo de procesamiento de cada subproceso es probablemente leer datos, decodificar, calcular el procesamiento, codificar y enviar respuestas.
API Core Asynchronous IO
Selector
La clase central de IO asíncrono, que puede detectar eventos en uno o más canales y distribuir eventos.
Use un hilo Select para escuchar eventos en múltiples canales y activar las respuestas correspondientes basadas en los controladores de eventos. No hay necesidad de asignar un hilo para cada canal.
Selección
Contiene el enlace del canal correspondiente a la información de estado del evento y la hora.
Resumir
Lo anterior es todo el contenido de este artículo sobre ensayos básicos de conocimiento de Java, espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!