2. Que es un Proceso? Un proceso es un programa ejecutándose dentro de su propio espacio de direcciones. Java es un sistema multiproceso, esto significa que soporta varios procesos corriendo a la vez dentro de sus propios espacios de direcciones.
3. Que es un Thread? Los threads-traducidos como hilos, hebras o contextos de ejecución- son espacios de código que la JVM ejecutará de forma simultanea en una maquina multiprocesador y de forma conmutada en maquina de un solo procesador, este es, la ejecución de los threads se realizará asignando un determinado quantum o espacio de tiempo a cada uno de los threads.
4. Que es un thread? Un hilo es una secuencia de código en ejecución dentro del contexto de un proceso. Los hilos no pueden ejecutarse ellos solos; requieren la supervisión de un proceso padre para correr.
5. Java en un Sistema multihilos? La Máquina Virtual Java (JVM) es un sistema multihilo. Es decir, es capaz de ejecutar varios hilos de ejecución simultáneamente. La JVM gestiona todos los detalles, asignación de tiempos de ejecución, prioridades, etc., de forma similar a como gestiona un Sistema Operativo múltiples procesos. La diferencia básica entre un proceso de Sistema Operativo y un Thread Java es que los hilos corren dentro de la JVM, que es un proceso del Sistema Operativo y por tanto comparten todos los recursos, incluida la memoria y las variables y objetos allí definidos. A este tipo de procesos donde se comparte los recursos se les llama a veces procesos ligeros (lightweightprocess).
6. Java Threads Thread (hilo, tarea) es la clase base de Java para definir hilos de ejecución concurrentes dentro de un mismo programa. En Java, como lenguaje O.O., el concepto de concurrencia está asociado a los objetos: Son los objetos los que actúan concurrentemente con otros.
7. Java Threads Las clases de objetos (hilos) que puedan actuar concurrentemente deben extender la clase Thread. Ejemplo: classmiClaseConcurrenteextendsThread {...}
8. La Clase Thread Las clases derivadas de Thread deben de incluir un método: public void run () Este método especifica realmente la tarea a realizar. La ejecución del método run de un Thread puede realizarse concurrentemente con otros métodos run de otros Thread y con el método main.
9. La Clase Thread La forma más directa para hacer un programa multihilo es extender la clase Thread, y redefinir el método run(). Este método es invocado cuando se inicia el hilo (mediante una llamada al método start() de la clase Thread). El hilo se inicia con la llamada al método run() y termina cuando termina éste.
10. Ejemplo 1 public class ThreadEjemplo extends Thread { publicThreadEjemplo(Stringstr) { super(str); } publicvoidrun() { for (int i = 0; i < 10 ; i++) System.out.println(i + " " + getName()); System.out.println("Termina thread " + getName()); } public static void main (String [] args) { new ThreadEjemplo("Pepe").start(); new ThreadEjemplo("Juan").start(); System.out.println("Termina threadmain"); } }
11. Salida del Código 0 Pepe 1 Pepe 2 Pepe 3 Pepe 0 Juan 4 Pepe 1 Juan 5 Pepe 2 Juan 6 Pepe 3 Juan 7 Pepe 4 Juan 8 Pepe 5 Juan 9 Pepe 6 Juan Termina thread Pepe 7 Juan 8 Juan 9 Juan Termina thread Juan
12. Iniciar una tarea: start El inicio de la ejecución de una tarea se realiza mediante el método start() heredado de Thread. start() es un método especial que invoca a run() y devuelve inmediatamente el control a la tarea que lo ha llamado.
13. Notas del Código La clase Thread está en el paquete java.lang. Por tanto, no es necesario el import. El constructor publicThread(Stringstr) recibe un parámetro que es la identificación del Thread. El método run() contiene el bloque de ejecución del Thread. Dentro de él, el método getName() devuelve el nombre del Thread (el que se ha pasado como argumento al constructor). El método main crea dos objetos de clase ThreadEjemplo y los inicia con la llamada al método start()(el cual inicia el nuevo hilo y llama al método run()). Obsérvese en la salida el primer mensaje de finalización del threadmain. La ejecución de los hilos es asíncrona. Realizada la llamada al método start(), éste le devuelve control y continua su ejecución, independiente de los otros hilos. En la salida los mensajes de un hilo y otro se van mezclando. La máquina virtual asigna tiempos a cada hilo
15. Resumen Creación/Ejecución de hilos en Java Un objeto concurrente pertenece a una clase que extiende Thread. Hay que redefinir el método run() que especifica la tarea concurrente. La ejecución de la tarea concurrente se realiza mediante el método start() (heredado de Thread).
16. Síntesis La clase Thread es la clase responsable de producir hilos funcionales para otras clases. Para añadir la funcionalidad de hilo a una clase simplemente se deriva la clase de Thread y se ignora el método run. Es en este método run donde el procesamiento de un hilo toma lugar, y a menudo se refieren a él como el cuerpo del hilo. La clase Thread también define los métodos start y stop, los cuales te permiten comenzar y parar la ejecución del hilo, además de un gran número de métodos útiles.
17. Ejemplo 2 class Hilo extendsThread { public Hilo(Stringstr) { super(str); } publicvoidrun() { for (int i = 0; i <= 100; i++) { System.out.println(i + " " + getName()); try { sleep((long) (Math.random() * 1000)); } catch (InterruptedException e) { } System.out.println("FIN! " + getName()); } } } classThreadMiProgr { publicstaticvoidmain(String[] args) { Hilo uno, dos; uno = new Hilo("Jamaica"); dos = new Hilo("Fiji"); uno.start(); dos.start(); System.out.println("main no hace nada"); } }
18. Practica: Cambia los siguientes elementos: uno.start(); dos.start (); Sutituyeestaslineasporlassiguientes: uno.run(); dos.run () ; Comenta los resultados
21. Prioridades en los Threads El criterio para la ejecución de múltiples hilos sobre una CPU se basa en prioridades: El sistema (JRE) selecciona para ejecutar en cada instante el hilo (ejecutable) con prioridad más alta. A igualdad de prioridad, selección arbitraria. Los hilos heredan la prioridad del hilo que los crea. La prioridad se puede cambiar: void setPriority (long x) long getPriority( ) Un hilo de prioridad baja sólo podrá ejecutarse cuando todos los hilos de prioridad superior pasen al estado "No ejecutable"
22. Reparto de tiempo (Time Slicing) Método de asignación de tiempo de CPU a diferentes hilos de igual (o mayor) prioridad. Cada intervalo de tiempo (ti) se selecciona un hilo a ejecutar en la CPU (prioridad >= al actual). * Un hilo puede ceder su tiempo: static void yield ( )
24. EL CICLO DE VIDA DE UN THREAD Cuando se instancia la clase Thread (o una subclase) se crea un nuevo Thread que está en su estado inicial ('New Thread' en el gráfico). En este estado es simplemente un objeto más. No existe todavía el thread en ejecución. El único método que puede invocarse sobre él es el método start().
25. EL CICLO DE VIDA DE UN THREAD Cuando se invoca el método start() sobre el hilo el sistema crea los recursos necesarios, lo planifica (le asigna prioridad) y llama al método run(). En este momento el hilo está corriendo, se encuentra en el estado ‘runable’.
26. EL CICLO DE VIDA DE UN THREAD Si el método run() invoca internamente el método sleep() o wait() o el hilo tiene que esperar por una operación de entrada/salida, entonces el hilo pasa al estado 'no runnable’ (no ejecutable) hasta que la condición de espera finalice. Durante este tiempo el sistema puede ceder control a otros hilos activos. Por último cuando el método run finaliza el hilo termina y pasa a la situación 'Dead' (Muerto).
27. Interfaz Runnable La interface Runnable proporciona un método alternativo a la utilización de la clase Thread, para los casos en los que no es posible hacer que la clase definida extienda la clase Thread. Esto ocurre cuando dicha clase, que se desea ejecutar en un hilo independiente deba extender alguna otra clase. Dado que no existe herencia múltiple, la citada clase no puede extender a la vez la clase Thread y otra más. En este caso, la clase debe implantar la interface Runnable, variando ligeramente la forma en que se crean e inician los nuevos hilos.
28. Interfaz Runnable: Ejemplo publicclassThreadRunneableimplementsRunnable { publicvoidrun() { for (int i = 0; i < 5; i++) { System.out.println(i + " " + Thread.currentThread().getName()); } System.out.println("Termina thread " + Thread.currentThread().getName()); } publicstaticvoidmain(String[] args) { new Thread(new ThreadRunneable(), "Pepe").start(); new Thread(new ThreadRunneable(), "Juan").start(); System.out.println("Termina threadmain"); } }
29. Interfaz Runnable: Ejemplo 2 classHiloThreadextendsThread { publicvoidrun() { while (true) { System.out.println("Hola Curso java Modulo 2, soy el hilo HiloTread"); } } } //Clase HiloRunnable classHiloRunnableimplementsRunnable { publicvoidrun() { while (true) { System.out.println("Hola Curso java Modulo 2, soy el hilo HiloRunnable"); } } } classThreadRunneable { publicstaticvoidmain(String[] args) { //Creamos un hilo del primer tipo //y lo ponemos en marcha HiloThreadht = new HiloThread(); ht.start(); //Creamos un hilo del segundo tipo //y lo ponemos en marcha Threadhr = new Thread(new HiloRunnable()); hr.start(); } }
30. Practica: Realiza un programa que implemente hilos en el cual se manejen prioridades.
32. Sockets Los sockets son un sistema de comunicación entre procesos de diferentes máquinas de una red. Más exactamente, un socket es un punto de comunicación por el cual un proceso puede emitir o recibir información.
33. Sockets Utilizan una serie de primitivas para establecer el punto de comunicación, para conectarse a una máquina remota en un determinado puerto que esté disponible, para escuchar en él, para leer o escribir y publicar información en él, y finalmente para desconectarse.
35. Funcionamiento Normalmente, un servidor se ejecuta sobre una computadora específica y tiene un socket que responde en un puerto específico. El servidor únicamente espera, escuchando a través del socket a que un cliente haga una petición. En el lado del cliente: el cliente conoce el nombre de host de la máquina en la cual el servidor se encuentra ejecutando y el número de puerto en el cual el servidor está conectado. Para realizar una petición de conexión , el cliente intenta encontrar al servidor en la máquina servidora en el puerto especificado.
36. Implementación La clase Socket se sitúa en la parte más alta de una implementación dependiente de la plataforma, ocultando los detalles de cualquier sistema particular al programa Java. Usando la clase java.net.Socket en lugar de utilizar código nativo de la plataforma, los programas Java pueden comunicarse a través de la red de una forma totalmente independiente de la plataforma. De forma adicional, java.net incluye la clase ServerSocket, la cual implementa un socket el cual los servidores pueden utilizar para escuchar y aceptar peticiones de conexión de clientes.
37. Modelo de comunicaciones con Java El servidor establece un puerto y espera durante un cierto tiempo (timeout segundos), a que el cliente establezca la conexión. Cuando el cliente solicite una conexión, el servidor abrirá la conexión socket con el método accept(). El cliente establece una conexión con la máquina host a través del puerto que se designe en puerto# l cliente y el servidor se comunican con manejadores InputStream y OutputStream
39. CLASES PARA LAS COMUNICACIONES DE RED EN JAVA Socket: Implementa un extremo de la conexión TCP. ServerSocket: Se encarga de implementar el extremo Servidor de la conexión en la que se esperarán las conexiones de los clientes. DatagramSocket: Implementa tanto el servidor como el cliente cuando se utiliza UDP. DatagramPacket: Implementa un datagrampacket, que se utiliza para la creación de servicios de reparto de paquetes sin conexión. InetAddress: Se encarga de implementar la dirección IP.
40. Tipos de sockets Sockets TCP Las aplicaciones piden al S.O. una comunicación controlada por TCP: Orientada a la conexión Comunicación fiable y ordenada También se denominan sockets de tipo Stream Sockets UDP ● Las aplicaciones piden al S.O. una comunicación controlada por UDP: Transferencia de bloques de datos Sin conexión ni fiabilidad ni entrega ordenada Permite difusiones También se denominan sockets de tipo Datagrama
41. Dentro del paquete java.net existen tres clases de sockets: Socket Cliente TCP ServerSocket Servidor TCP DatagramSocket Cliente/Servidor UDP ● También hay otras clases auxiliares que facilitan la programación de aplicaciones en red
42. Clase InetAddress InetAddress es la clase que se utiliza para almacenar direcciones IP Algunos métodos: InetAddressgetByName(String nombre) Obtiene la dirección IP asociada a un nombre StringgetHostAddress() Devuelve la dirección IP en formato "aa.bb.cc.dd“ StringgetHostName() Devuelve el nombre del host
43. Sockets TCP Cliente: Inicia la conexión con el servidor Especifica la dirección IP y el puerto del proceso servidor Cuando crea un socket establece la conexión con el servidor Servidor: Ha de estar en ejecución Debe haber creado un socket (1) donde recibir a los clientes que conectan con él Espera a que algún cliente se conecte
51. Sockets UDP No se establece una conexión previa al envío/recepción de datos. Los datos se envían en bloques (datagramas). Los datagramas son objetos de la clase DatagramPacket. Cada datagrama contiene la dirección de destino y el puerto. Los datagramas pueden no llegar en el mismo orden en que se enviaron. Permiten difusiones (broadcast y multicast).
52. Sockets UDP Para enviar o recibir datagramas (DatagramPacket) se utilizan objetos DatagramSocketo MulticastSocket. Se diferencian por el tipo de canal: DatagramSocket -- Punto a punto no dedicado MulticastSocket -- Multipunto
53. Sockets UDP Dos clases: DatagramSocket: para enviar o recibir datagramas) DatagramPacket: paquete de datos o datagrama
54. DatagramPacket Paquete de datos (datagrama) a transmitir o recibir a través de un socket UDP (objeto DatagramSocket). Un datagrama consta de: Una cabecera: dirección de origen y destino del paquete, el puerto, la longitud del paquete, un checksum, etc. Cuerpo: datos del paquete.
55. DatagramPacket: constructores Para recibir datos: DatagramPacket (byte[] buffer, int n) Para enviar datos: DatagramPacket(byte[] buffer, int n, InetAddressdest, intpuerto) buffer: array que almacenará los datos a enviar o recibir- n: tamaño máximo del datagrama a enviar o recibir dest: es la dirección de la máquina destinataria del datagrama puerto: puerto en el que atiende las peticiones el servidor
56. DatagramPacket: métodos InetAddressgetAddress() -- Devuelve la dirección almacenada en el paquete intgetPort() --Devuelve el puerto almacenado en el paquete byte[] getData() -- Devuelve los datos almacenados en el paquete intgetLength() --Devuelve el tamaño de los datos almacenados en el paquete voidsetAddress(InetAddressdest) -- Establece la dirección dedestino voidsetPort(int puerto) -- Establece el puerto destino voidsetData(byte[] buffer)-- Establece los datos a enviar voidsetLength(int n) -- Establece el tamaño máximo del paquete
57. DatagramSocket: constructores y métodos Constructores DatagramSocket() -- Crea un socket en cualquier puerto que haya libre en la máquina local. DatagramSocket(intpuerto) -- Crea un socket en el puerto especificado Métodos voidsend(DatagramPacket p) -- Envia el datagrama p a través del socket voidreceive (DatagramPacket p)--Recibe el datagrama p a través del socket voidclose() -- Cierra el socket