jueves, 16 de julio de 2015

SERVIDOR-CLIENTE CONCURENTE

¿QUÉ ES CONCURRENCIA?


Se habla de concurrencia cuando se ejecutan varios procesos simultáneos.
La concurrencia aparece cuando dos o más procesos son simultáneos. Un caso particular es el paralelismo (programación paralela).

  • Los procesos pueden “competir” o colaborar entre sí por los recursos del sistema. Por tanto, existen tareas de colaboración y sincronización. 
  • Java posibilita la programación concurrente a través de threads. 
  • Los threads son procesos ligeros, con línea de flujo de control propia pero que comparte el espacio de direcciones del programa. „ 
  • Los threads hacen posible la ejecución concurrente de código. „ Los cambios de contexto son menos costosos en tiempo de ejecución.



BENEFICIO DE HACER UN PROGRAMA CONCURRENTE


  • Velocidad de ejecución. Al subdividir un programa en procesos, éstos se pueden “repartir” entre procesadores o gestionar en un único procesador según importancia.



Java proporciona un API para el uso de hilos: clase Thread dentro del paquete java.lang.Thread. Cuando arranca un programa existe un hilo principal (main), y luego se pueden generar nuevos hilos que ejecutan código en objetos diferentes o el mismo. La clase Thread dispone de una serie de métodos para caracterizar el thread/hilo en el programa, es importante sobreescribir el método run(), para que el hilo realice su función e invocar al método start() para darle vida al hilo.

Esquema de los diferentes estados en los que puede encontrarse un hilo.



  • Nuevo: Se ha creado un objeto hilo, pero todavía no se le ha asignado ninguna tarea. Para ello, se ha de llamar a su método start() y el hilo pasará al estado preparado.
  • Preparado: El hilo está preparado para ejecutarse, pero el planificador de hilos es quién debe decidir si puede hacerlo o debe esperar.
  • En ejecución: Una vez el hilo puede acceder a tiempo de CPU, se ejecutará. Si el hilo finaliza su trabajo completamente, pasará al estado muerto. Si el planificador de hilos decide que ha cumplido su periodo de tiempo y el hilo no ha finalizado su trabajo, pasará al estado preparado y esperará a que el planificador de hilos vuelva a darle permiso para ejecutarse.
  • Bloqueado: El hilo no puede ejecutarse porque espera que ocurra algo. En cuanto ocurra lo que le está dejando bloqueado, pasará al estado preparado.
  • Muerto: El hilo ha finalizado su tarea y deja de existir.

EJEMPLO PRÁCTICO

Realizar un programa concurrente en java, mediante la utilización de hilos y sockects. Este programa indica al cliente que ingrese un mensaje, este va al servidor y el servidor le devuelve el mismo mensaje.

CLASE CLIENTE
  • Se importa las librerías de las clases necesarias para el programa
  • La clase ClienteEco permite el envió de un mensaje a un servidor y  la vez recibe el mismo mensaje atra vez de este. Para la ejecución del programa se colocara el método main el cual recibe argumento de entrada del tipo String.
  • En esta clase se crea un objeto del tipo Socket, llamado cliente, este se lo instancia con el constructor de la clase, el cual recibe como argumento de entrada dos parámetros, uno la dirección IP y segundo el puerto por el cual el cliente será escuchado.
  • Creamos un objeto del tipo BufferedReader llamado lecturaCliente, instanciado con el constructor de la clase, recibiendo como argumento de entrada lo que va a leer.
  • Se crea un objeto del tipo PrintWriter, llamado escribir, se lo instancia con el constructor de la clase enviándolo como argumento de entrada lo que se enviará al cliente. 
  • Creamos otro BufferedReader llamado entrada, instanciandolo con el constructor de la clase y enviando como argumento de entrada, que leerá desde el teclado.
  • A continuación se imprimirá por pantalla el mensaje, Ingrese el mensaje, donde el usuario ingresará el mismo.



  • Se realiza un condicional, en donde mientras el cliente ingrese algún mensaje, se realizará lo siguiente.
  •  Se enviará el mensaje al servidor mediante el objeto creado escribir.
  • Por pantalla se imprimirá el mensaje enviado por el servidor al cliente.


  • Finalmente se utiliza el método close(), para cerrar el socket utilizado.
  • Es importante el manejo de excepciones con try-catch.




CLASE MANEJOTHREAD

  • Se importa las librerías de las clases necesarias para el programa
  • La clase ManejoThread hereda de la clase Thread, está permite la utilización de hilos para generar un programa concurrente.
  • Presenta 3 tipos de atributos uno del tipo Socket, otro de tipo int y el último de tipo String.
  • Se realiza el constructor de inicializacion de la clase, mandando como argumento de entrada un objeto del tipo socket.


  • Como los atributos utilizados son private es necesario la creación de los getters y setters de cada uno.



  • Como esta clase se extiende de Thread, se debe sobreescrirbir el método run(), este tendrá la funcionalidad de los hilos a ejecutarlra
  • Para esto se crea un objeto del tipo BufferedReader llamado lectura, instanciado con el constructor de la clase, recibiendo como argumento de entrada lo que va a leer.
  • Se crea un objeto del tipo PrintWriter, llamado escribir, se lo instancia con el constructor de la clase enviándolo como argumento de entrada lo que se enviará al cliente. 
  • Es necesario un boolean para controlar la ejecución de los hilos.
  • Se crea un lazo condicional mientras sea verdadera se realizará lo siguiente, el atributo sms se instancia con el objeto lectura, este permite leer el mensaje que envió el cliente.
  • Por pantalla se imprimirá el mensaje que se recibió del cliente.
  • Se usa un condicional para comprobar si el mensaje es nulo solo se lo imprime, caso contrario el mensaje se envía al cliente.
  • Finalmente se cierra el socket creado.
  • Es importante el manejo de excepciones, para lo cual se utilizó el try y catch





CLASE SERVIDOR

  • Importamos las librerías de las clases necesarias


  • La clase Servidor recibirá el mensaje del cliente y lo imprimirá por pantalla, a la  vez que este mensaje es devuelto al cliente
  • Se utiliza el método main para la ejecución del programa, este recibe un argumento de entrada el cual es el número de puerto por donde escuchará las peticiones.
  • Se utiliza un condicional, el cual comprueba que el número de argumentos de entrada sea correcto caso contrario manda un mensaje de información.





  • Se crea un atributo de tipo int, instanciado con el número de puerto ingresado ha este se lo realiza un casting.
  • Se crea un objeto del tipo ServerSocket, llamado serverSocket, este se lo instancia con el constructor de la clase, se lo mando como argumento de entrada el numero de puerto
  • Si todo se ejecutó de manera correcta, por pantalla se imprimirá Escuchando, el cual indica que el servidor esta esperando peticiones de clientes.


  • Se realiza un lazo infinito, en donde se creará un objeto del tipo Socket, aquí se establece la conexión entre cliente y servidor mediante el socket creado. Por pantalla se imprimirá que la conexión fue aceptada. 
  • Se crea un objeto del tipo ManejadorThread, este recibe como argumento de entrada un objeto del tipo Socket en este caso será el cliente.
  • Se crea un objeto del tipo Thread, que será el hilo que se crea para atender a cada cliente, este recibe como argumento de entrada un objeto del tipo ManejadorThread. Finalmente utilizamos el método start(), para darle vida al Thread.




  • Hay que recordar que es importante utilizar el manejo de las excepciones, utilizando el try y catch.










SALIDA DEL PROGRAMA

  • EJECUCIÓN DEL SERVIDOR

  • EJECUCIÓN DE  CLIENTES

  • EJECUCIÓN DE PETICIONES DE 3 CLIENTES

BIBLIOGRAFÍA:
http://www.ingenieroinformatico.org/2012/01/concurrencia-en-java/
http://www.ctr.unican.es/asignaturas/procodis_3_II/Doc/Procodis_3_01.pdf

http://www2.ulpgc.es/hege/almacen/download/20/20233/tema1.pdf




domingo, 28 de junio de 2015

FLUJOS DE ENTRADA Y SALIDA EN JAVA


¿QUÉ ES UN FLUJO O STREAM?

La entrada (input) y salida (output) en java se implementa en el paquete java.io

En términos de programación se denomina entrada a la posibilidad de introducir datos hacia un programa; salida sería la capacidad de un programa de mostrar información al usuario.

La E/S en java se basa en el concepto de flujo o denominado STREAM.

El flujo es una secuencia ordenada de datos que tiene una fuente (flujos de entrada) o un destino (flujos de salida).

Los streams soportan varios tipos de datos:
  • bytes simples, tipos de datos primitivos, caracteres localizados, y objetos
Los Streams se caracterizan por se unidireccionales, es decir que un Stream se utilizara solo para leer, solo para escribir, pero no ambas acciones al mismo tiempo.


En Java se accede a la E/S estándar a través de campos estáticos de la clase java.lang.System
  •  System.in implementa la entrada estándar 
  • „ System.out implementa la salida estándar
  • „ System.err implementa la salida de error


TIPOS DE STREAMS

La API de Java diferencia entre los streams de caracteres y streams de bytes.

  • Streams de bytes (InputStream y OutputStream) 
Los Streams de Bytes como su nombre lo indica trabaja con bytes. Los bytes a leer se leeran en forma unitaria(es decir 8 bits por byte).
Son utilizados para leer y escribir información que esta almacenada en forma binaria, como por ejemplo archivos.
La Superclase utilizada para leer streams orientados a byte es la clase InputStream. A partir de esta clase - la cual es abstracta – heredan todas las clases concretas que se utilizan para leer información en forma binaria.
La superclase utilizada para escribir streams orientados a bytes es la clase OutputStream. A partir de esta clase - la cual es abstracta – heredan todas las clases concretas que se utilizan para escribir información en forma binaria.






  • Streams de caracteres (Reader y Writer):
Los Streams de caracteres operan con caracteres como unidad de trabajo. Los caracteres a leer están formados por 2 bytes(es decir 16 bits por carácter).
Son utilizados para leer y escribir información que esta almacenada en forma de texto, como por ejemplo archivos.
La Superclase utilizada para leer streams orientados a carácter es la clase Reader. A partir de esta clase - la cual es abstracta – heredan todas las clases concretas que se utilizan para leer información en forma textual.
La Superclase utilizada para escribir streams orientados a carácter es la clase Writer. A partir de esta clase - la cual es abstracta – heredan todas las clases concretas que se utilizan para escribir información en forma textual.





EXCEPCIÓN

La excepción que es lanzada cuando algún tipo de operación I/O ha fallado es IOException. Esta excepción debe de ser tratada ya sea manejándola con un bloque de código try-catch en el mismo momento que se realice la operación o dejando que se propague hacia arriba en la pila de llamadas utilizando throws IOException.



SERIALIZACIÓN

La serialización de un objeto consiste en obtener una secuencia de bytes que represente el estado de dicho objeto. Esta secuencia puede utilizarse de varias maneras (puede enviarse a través de la red, guardarse en un fichero para su uso posterior, utilizarse para recomponer el objeto original, etc.). 
Para poder transformar el objeto en una secuencia de bytes, el objeto debe ser serializable.
Un objeto es serializable si su clase implementa la interface Serializable.
La interface Serializable se encuentra en el paquete java.io Es una interface vacía. No contiene ningún método.

ESCRITURA DE OBJETOS EN UN FICHERO BINARIO

Para escribir objetos en un fichero binario en Java se utiliza la clase ObjectOutputStream derivada de OutputStream.
Un objeto ObjectOutputStream se crea a partir de un objeto FileOutputStream asociado al fichero.
El constructor de la clase es:
ObjectOutputStream(OutputStream nombre);

Lanza una excepción IOException.
La clase proporciona los siguientes métodos:
  •  método writeObject(Object objeto) para escribir el objeto en el fichero. 
  • método defaultWriteObject() de la clase ObjectOutputStream realiza de forma automática la serialización de los objetos de una clase. Este método se invoca en el método writeObject().
  • defaultWriteObject() escribe en el stream de salida todo lo necesario para reconstruir los objetos:
  1. - La clase del objeto.
  2. - Los miembros de la clase (atributos).
  3. - Los valores de los atributos que no sean static o transient.
LECTURA DE OBJETOS EN UN FICHERO BINARIO
Para leer los objetos contenidos en un fichero binario que han sido almacenados mediante ObjectOutputStream se utiliza la clase ObjectInputStream derivada de InputStream.
Un objeto ObjectInputStream se crea a partir de un objeto FileInputStream asociado al fichero.
El constructor de la clase es:
ObjectInputStream(InputStream nombre);
Lanza una excepción IOException.
La clase proporciona el método readObject() que devuelve el objeto del fichero (tipo Object).
Es necesario hacer un casting para guardarlo en una variable del tipo adecuado.
Es necesario cerrar el flujo de bytes de salida para esto se usa el método close().


EJEMPLO:
Escribir y guardar en un archivo los datos de un paciente, para luego poder leerlos mediante la utilización de flujos de entrada y salida.

1. Creación de la Clase Paciente
La clase Paciente implementa la interfaz Serializable, la cual le permite la transformación de un objeto en una secuencia de bytes que pueden ser posteriormente leídos para reconstruir el objeto original.
Esta Clase presenta 5 atributos: Documento, nombre, género, fecha de nacimiento y la cantidad de pacientes.
Se crea los respectivos constructores de la clase, al igual que los métodos getters y setters de cada atributo.
Finalmente se sobreescribe el método TosString.
A continuación se muestra la clase Paciente realizada en NETBEANS.


Aplicación para escribir en un archivo mediante la utilización de la clase ObjectOutputInputString



Salida


Aplicación para leer en un archivo mediante la utilización de la clase ObjectInputString


Salida

domingo, 21 de junio de 2015

EXCEPCIONES EN JAVA

¿Qué es una excepción?

Una excepción es un evento que ocurre durante la ejecución del programa, que interrumpe el flujo normal de las sentencias. ( Algo que altera la ejecución normal del programa).
Muchas clases de errores pueden generar excepciones: desde problemas de hardware, como la avería de un disco duro, a los simples errores de programación, como tratar de acceder a un elemento de un array fuera de sus límites, cuando se hace una división entre cero,  cuando un objeto es ‘null’ y no puede serlo, cuando no se abre correctamente un fichero, etc. Cuando se produce una excepción se muestra en la pantalla un mensaje de error y finaliza la ejecución del programa.

El tratamiento de excepciones en Java es un mecanismo del lenguaje que permite gestionar errores y situaciones excepcionales

Todas las excepciones en Java se representan,  a través de objetos que heredan, en última instancia, de la clase java.lang.Throwable.


Jerarquía de excepciones

La clase principal de la cual heredan todas las excepciones Java es Throwable. De ella nacen dos ramas: Error y Exception. La primera representa errores de una magnitud tal que una aplicación nunca debería intentar realizar nada con ellos (como errores de la JVM, desbordamientos de buffer, etc) y que por tanto no tienen cabida en este artículo. La segunda rama, encabezada por Exception, representa aquellos errores que normalmente si solemos gestionar, y a los que comúnmente solemos llamar excepciones.

Vamos a ver tres de las palabras reservadas para tratamiento de excepciones:
BLOQUE TRY
Todo el código que vaya dentro de esta sentencia será el código sobre el que se intentará capturar el error si se produce y una vez capturado hacer algo con él. 
BLOQUE CATCH
Se define el conjunto de instrucciones necesarias o de tratamiento del problema capturado con el bloque try anterior. Es decir, cuando se produce un error o excepción en el código que se encuentra dentro de un bloque try, pasamos directamente a ejecutar el conjunto de sentencias que tengamos en el bloque catch.

Después de catch se encuentra paréntesis donde pone “Exception e”. Esto significa que cuando se produce un error Java genera un objeto de tipo Exception con la información sobre el error y este objeto se envía al bloque catch.


BLOQUE FINALLY
Ees un bloque donde podremos definir un conjunto de instrucciones necesarias tanto si se produce error o excepción como si no y que por tanto se ejecuta siempre.


Ejemplo:


EXCEPCIONES PROPIAS

Para crear sus propias excepciones personalizadas en Java , es necesario ampliar el supertipo excepción. 
Debe tener en cuenta los siguientes punto a la hora de escribir o declara una excepción:
  • Todas las excepciones deben ser un hijo de Throwable.
  • Si desea escribir una excepción comprobada que se aplica de forma automática por el Handle o el Declare Rule, es necesario extender la clase de excepción de Exception.
  • Si se desea escribir una excepción de tiempo de ejecución o una RuntimeException, es necesario extender la excepción deRuntimeException
Podemos definir nuestra propia clase de excepción de la siguiente manera:



Esta aplicación permite calcular la raíz cuadrada de un número, pero captura excepciones cuando el número ingresado por el teclado es menor que cero.


lunes, 15 de junio de 2015

INTERFACES

¿Qué es una interfaz?
Una interfaz en Java es una clase abstracta pura, es decir una clase donde todos los métodos son abstractos, pero ninguno de ellos se implementa. 


Para crear una interfaz, se utiliza la palabra clave interfaz en lugar de class. La interfaz puede definirse public o sin modificador de acceso, y tiene el mismo significado que para las clases.
Para indicar que una clase implementa los métodos de una interfaz se utiliza la palabra clave implements. El compilador se encargará de verificar que la clase efectivamente declare e implemente todos los métodos de la interfaz. Una clase puede implementar más de una interfaz.



Ventajas al utilizar interfaces:

  • Se organiza la programación.
  • Obligar a que ciertas clases utilicen los mismos métodos (nombres y parámetros).
  • Establecer relaciones entre clases que no estén relacionadas.
  • Otra ventaja clara de las interfaces es que nos permiten declarar constantes que van a estar disponibles para todas las clases que queramos (implementando esa interfaz). Nos ahorra código evitando tener que escribir las mismas declaraciones de constantes en diferentes clases.

INTERFAZ COMPARABLE

La interfaz Comparable permite comparar 2 objetos, permitiendo hacer ordenaciones de los mismos. Al implementar esta interfaz, nos obliga a implementar el método compareTo (Object o).


EJEMPLO:

Este ejemplo permitirá tener una lista de estudiantes, la cual será presentada por orden alfabético, por edad y por su irá.
Para ello se creará 3 clases:

  1. Estudiante
  2. Curso
  3. Aplicación
  • CLASE ESTUDIANTE
Paquetes importados 



Atributos de Estudiante
La clase Estudiante implementará la interfaz COMPARABLE.



Constructores por defecto e inicialización 



Métodos getters and setters
Estos sirven para poder obtener o modificar los atributos de Estudiante, debido a que su acceso es privado.



Método para obtener la edad
Este método calcula la edad a partir del año de nacimiento de una persona.


Método de la interfaz compareTo
Este método es obligado a usarse al implementar la interfaz Comparable.


  • CLASE CURSO
Paquetes importados
Atributo, Constructor y Método getter y setter




Método para agregar estudiantes e imprimir

Método para ordenar por nombre


  • CLASE APLICACIÓN
Implementación del método main


SALIDA


Método para ordenar por edad



SALIDA


Método para ordenar por ira



SALIDA



INTERFAZ CLONEABLE

La interfaz Cloneable permite que una clase  pueda realizar la copia de objetos tal cual, permitiendo hacer por tanto duplicados exactos, aunque eso sí, objetos al fin y al cabo distintos.  Al usar esta interfaz es como si al clonar un objeto tuviéramos un gemelo, son parecidos pero personas distintas.

EJEMPLO:
Usaremos la clase Estudiante del ejemplo anterior, la cual implementará la interfaz Cloneable.






APLICACIÓN





Cuando se quiera que los objetos de una clase puedan ser copiados debemos implementar la interfaz Cloneable y el método clone().  Esto suele ser útil por ejemplo cuando tenemos una clase con muchos atributos o propiedades, y al trabajar con ella por ejemplo para calcular algún dato no queremos trabajar con ella directamente para no modificar el objeto original. Una opción es crear un objeto clonado y trabajar directamente sobre éste, sin afectar al original en ningún atributo. En realidad, la clonación de objetos será algo que nos puede resultar útil para muchas cosas.
Y por último, recordar que tratar de realizar una asignación de tipo p2 = p1 sería erróneo, ya que no generaríamos un clon sino dos variables que estarían apuntando al mismo objeto, no a distintos objetos.[]


BIBLIOGRAFIA:
http://aprenderaprogramar.com/index.php?option=com_content&view=article&id=671:para-que-sirven-las-interfaces-java-implementar-una-interfaz-del-api-ventajas-y-ejemplos-basicos-cu00697b&catid=68:curso-aprender-programacion-java-desde-cero&Itemid=188

http://elvex.ugr.es/decsai/java/pdf/AC-interfaces.pdf

http://www.aprenderaprogramar.com/index.php?option=com_content&view=article&id=587:ejercicio-ejemplo-resuelto-interface-comparable-y-metodo-compareto-api-java-comparar-objetos-cu00911c&catid=58:curso-lenguaje-programacion-java-nivel-avanzado-i&Itemid=180

http://www.aprenderaprogramar.com/index.php?option=com_content&view=article&id=584:ejercicio-y-ejemplo-resuelto-interface-cloneable-y-metodo-clone-del-api-java-como-duplicar-objetos-cu00910c&catid=58:curso-lenguaje-programacion-java-nivel-avanzado-i&Itemid=180

http://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html