1/15/2004

MEJORAS QUE TRAJO CONSIGO EL J2SE1.4: NIO (I)

Java Technology

Ahora, con el J2SE1.5 a punto de caramelo, quizá es buen momento para ver cuáles fueron las mejoras de la versión anterior, que quizá no habéis llegado a utilizar.

Información tomada a partir del JDK1.4 Tutorial de Manning.

Este primer post trata sobre el NIO (New I/O):

El paquete java.nio aporta las siguientes características al preexistente java.io:
1. block-oriented: opera sobre bloques, buscando obtener las mismas prestaciones que otros lenguajes, como C ó C++.
2. Utilización de buffers directos, que no utilizan buffers Java.
3. E/S no bloqueante, simplificando la programación multithreading.

Los elementos fundamentales, que se añaden al concepto anterior de "stream", son los siguientes:
1. Canal -channel-: fuentes y destinos de datos secuenciales, solo que leen los datos en pedazos, no byte a byte. Además, un canal puede ser bidireccional.
2. Buffer: donde se almacenan los trozos de datos. Normalmente son muy grandes.

- Obtención de un canal:
FileInputStream fin = new FileInputStream( infile );
FileChannel inc = fin.getChannel();

- Creación de un buffer:
ByteBuffer buffer = ByteBuffer.allocate( 1024 );

Tb. existen los IntBuffer, ShortBuffer, FloatBuffer, ...

- Lectura:

Se pasa de:
public int read( byte[] b, int off, int len );
, a:
public int read( ByteBuffer dst );

- Escritura:

Se pasa de:
public void write( byte[] b, int off, int len );
, a:
public int write( ByteBuffer src );


Buffers

También se puede utilizar directamente un buffer mediante sus métodos get y put. Es importante entender que cuando se lee de un canal, se escribe en un buffer, y viceversa.


- Lectura y Escritura de otros tipos desde un ByteBuffer:

Aquí hay que recordar el tamaño en bytes de cada tipo: byte, short, float, ...

IMPORTANTE: la ordenación por defecto de un ByteBuffer es BigEndian (MSB antes), pero puede cambiarse mediante el método order(ByteOrder).

Realmente, esta nueva manera de implementar E/S me recuerda a la manera de C con la estructura FILE * y los métodos fopen, ... ¡qué tiempos!

Buffers Directos

En lugar de utilizar buffers intermedios en la JVM para interactuar con el exterior, se utiliza la memoria del entorno de ejecución directamente:

ByteBuffer buffer = ByteBuffer.allocateDirect( 1024 );

No es buena idea utilizarlo siempre, ya que cuesta más recursos. Sólo cuando sea necesario por velocidad.


File Locking

* Tipos de bloqueos:

1. Mandatory lock
Evita que un fichero o la porción de un fichero sea accedido.

2. Advisory lock
Evita que otros "locks" adquieran la misma región.

También hay otra diferenciación:

1. Exclusive
Como los bloqueos del synchronized.

2. Shared
No evitan que otros threads adquieran el lock, sino que evitan que bloqueos exclusivos lo hagan.




FileOutputStream fout = new FileOutputStream( "abc.txt" );
FileChannel fc = fout.getChannel();
FileLock fl = fc.lock( 20, 20, false );
, donde se están bloqueando los bytes 20 a 39 del fichero abc.txt, de manera exclusiva

Todo el fichero:
FileOutputStream fout = new FileOutputStream( "abc.txt" );
FileChannel fc = fout.getChannel();
FileLock fl = fc.lock();




No hay comentarios: