Tema 2: Aplicaciones Multihilo, Cliente Servidor

Anuncio
Servidores Multiproceso
PID=1 atiende A
Tema 2:
Aplicaciones Multihilo,
Cliente Servidor
PID=2 atiende B
Web Server
process_new_connection()
Web_Server_Main ()
t=1. B puja
{
{
Multiples
Clientes
Concurrente
if ((pid = fork()) == 0)
for (;;)
{
{
child_main(slot);
new_connection = accept
(i, NULL, NULL);
Process_new_connection();
}
}
ap_scoreboard_image>parent[slot].pid = pid;
return 0;
}
1
Porqué Multitarea
(multiples hilos o procesos)
PID=3 atiende ..
Fork()
Fork()
t=1. A puja
}
2
Creación de procesos
int pid;
if (pid= fork()) == -1) perror(“error”);
else if (pid == 0) /*código del proc. hijo*/
else /* código del proc. padre */
Para poder cancelar tareas
independientemente.
Algunos problemas son intrinsecamente
paralelos: Simuladores, Servidores,
Recolectores,..
Para beneficiarse de hardware con multiples
procesadores.
El núcleo del SO. con la llamada fork():
1. Busca una entrada libre en la tabla de
procesos y reservar memoria.
2. Asigna un identificador único al pro. hijo.
3. Realiza las copias del contexto del proc.
padre para el proc. hijo.
4. Copia las tablas de control de ficheros del
proc. padre para el proc. hijo.
5. Retorna al proceso padre el pid del hijo y
al hijo el valor cero.
P_padre
3
P_hijo
4
Procesos pesados vs. ligeros (I)
Procesos pesados vs. ligeros (II)
Proceso pesado = proceso unix o win32 o ..
Proceso ligero = hilo (thread).
La compartición de una CPU entre multiples tareas de tal
manera que “se minimice el tiempo requerido para
cambiar entre tareas”.
Un proceso pesado en un sistema operativo se representa por su código,
datos en memoria, y el estado de los registros de la máquina PCB.
Esto se consigue “compatiendo el máximo posible del
entorno de ejecución del programa” entre las diferente
tareas de tal manera que muy poca información de estado
se necesita guardar y cargar cuando se cambie de tareas.
Los hilos de un mismo proceso pesado COMPARTEN el espacio de memoria.
Los hilo siempre existen dentro de un proceso pesado,
lo necesitan.
Para poder soportar procesos ligeros (hilos de control), se
dispone de múltiples pilas, una por cada hilo creado.
5
Hilos en Java (I)
Implementaciones de Hilos
A parent process may spawn child processes.
Una clase Thread gestiona un único hilo secuencial de control.
Los hilos pueden crearse y destruirse dinámicamente.
A process may spawn child threads
a process
parent process
6
main thread
child thread 1
Thread
child processes
child thread 2
run()
Los hilo siempre existen dentro de un proceso pesado, lo necesitan.
Programas que implementan la gestión de hilos, p.ej. Java Virtual Machine.
MyThread
•Las aplicaciones multihilo se ejecutan dentro del proceso del
programa.
run()
La clase Thread ejecuta instrucciones incluidas
en su método run(). El código real ejecutado
depende de la implementación dada para el
método run() en una clase derivada.
class MyThread extends Thread {
public void run() {
//......
}
}
También existen sistemas operativos que implementan en su kernel la
gestión de hilos: Windows NT, y muchas variantes de Unix.
• en este caso los hilos también están dentro de un proceso.
7
8
Ejemplo Hilos en Java (I)
import SomeThread ;
public class RunThreads
{
public static void main (String[] args)
{
SomeThread p1 = new SomeThread (1);
p1.start ();
Ejecución de Ejemplo
public class SomeThread extends Thread {
int myID ;
SomeThread (int id) {
this.myID = id;
}
public void run( ) {
int i;
for (i = 1; i < 11; i++)
System.out.println ("Thread"+ myID + ": " + i);
}
} //end class SomeThread
SomeThread p2 = new SomeThread (2);
p2.start ();
SomeThread p3 = new SomeThread (3);
p3.start ();
}
}// end class RunThreads
Una clase Thread tiene que implementar el metodo run(),
Una clase Thread se inicia llamando al metodo start().
9
Se puede implementar el método run() directamente desde el
interfaz Runnable, y asociarle un Thread para su ejecución.
Este manera de usar hilos es más versátil, ya que puede
derivarse de otras clases.
target
run()
MyRun
run()
Salida Ejecución RunThreads con sleep(10):
Thread1: 1
Thread2: 1
Thread3: 1
Thread1: 2
Thread2: 2
Thread3: 2
Thread2: 3
Thread1: 3
Cada 10 seg. los 3
Thread3: 3
hilos escriben
Thread2: 4
“concurrentemente”.
Thread1: 4
Thread3: 4
Thread2: 5
Thread3: 5
Thread1: 5
Thread2: 6
Thread3: 6
Thread1: 6
Thread2: 7
Thread3: 7
Thread1: 7
Thread2: 8
10
Thread3: 8
Ejemplo Hilos en Java (II)
Hilos en Java (II)
Runnable
Salida Ejecución RunThreads:
Thread3: 1
Thread3: 2
Thread3: 3
Thread1: 1
Thread1: 2
Thread1: 3
Thread1: 4
Thread1: 5
Thread1: 6
Totalmente
Thread1: 7
Thread1: 8
“Concurrente”
Thread1: 9
Thread1: 10
(aunque la
Thread3: 4
Thread3: 5
salida de linux
Thread3: 6
vs. Window
Thread3: 7
Thread3: 8
suele diferir)
Thread3: 9
Thread3: 10
Thread2: 1
Thread2: 2
Thread2: 3
Thread2: 4
Thread2: 5
Thread2: 6
Thread2: 7
Thread2: 8
public class RunThreads2
{
public static void main (String[] args)
{
Thread p1 = new Thread(new SomeThread2(1));
p1.start();
Thread
Thread p2 = new Thread(new SomeThread2(2));
p2.start();
Public interface Runnable {
public abstract void run();
}
Thread p3 = new Thread(new SomeThread2(3));
p3.start();
}
class SomeThread2 implements Runnable {
int myID;
SomeThread2(int id) {
this.myID = id;
}
public void run() {
int i;
for (i = 1; i < 11; i++)
System.out.println ("Thread"+myID + ": " + i);
}
} //end class SomeThread
}
class MyRun implements Runnable {
public void run() {
//.....
}
}
Un constructor de clase Thread:
public Thread(Runnable target)
11
12
¿hilo finalizado? (I)
Ciclo de vida de un hilo en Java
public class RunThreads3
{
public static void main (String[] args)
{
int originalThreadCount = Thread.activeCount( );
for (int i=0; i<10; i++) {
Thread p = new Thread(new SomeThread3());
p.start();
}
sleep(),join()
start()
while (Thread.activeCount() > originalThreadCount ){
// loop until all child threads have exited.
}
start() comienza el hilo, siempre llama a run()
// todos los hilos finalizados, continua.
}
sleep(x) duerme el hilo un tiempo.
}
join() espera a que otro hilo finalice.
13
¿hilo finalizado?(II): isAlive()
14
¿hilo finalizado? (III): join()
// Create and start a thread
Thread thread = new MyThread();
thread.start();
// Create and start a thread
Thread thread = new MyThread();
thread.start();
// Check if the thread has finished
// in a non-blocking way
while (thread.isAlive()) {
// Thread has not finished
} else {
// Wait indefinitely for the thread to finish
try {
Bloqueante
thread.join();
// otro hilo finalizado, continua.
…….
} catch (InterruptedException e) {
// Thread was interrupted
// otro hilo finalizado, continua.
}
}
15
16
Race Condition en Threads
Syncronize en Threads
class SomeThread3 implements Runnable {
static int count=0;
class SomeThread3 implements Runnable {
static int count=0;
Instruction execution order:
SomeThread3() {
super();
}
public void run() {
update();
}
static public void update( ){
int myCount = count;
int second = (int)(Math.random( ) * 500);
try {
Thread.sleep(second);
}
catch (InterruptedException e) { }
myCount++;
count = myCount;
System.out.println("count= "+count);
•
•
•
•
Instruction execution order:
SomeThread3() {
super();
}
public void run() {
update();
}
static public synchronized void update( ){
int myCount = count;
int second = (int)(Math.random( ) * 500);
try {
Thread.sleep(second);
}
catch (InterruptedException e) { }
myCount++;
count = myCount;
System.out.println("count="+count);
}
Hilo 1 llama update,
Hilo 2 llama update,
…
.
• Hilo 1: “count = 1”
Time
• Hilo 2: “count = 2”
• Hilo 3: “count = 2”
• Hilo 4: “count = 1”
• Hilo 5: “count = 1”
• …
• .
• .
No DESEADO
• Hilo 1 llama update,
•
Hilo 1: “count = 1”
• Hilo 2 llama update,
•
•
•
•
Time
•
•
•
Hilo 2: “count = 2”
Hilo 3 llama update,
Hilo 3: “count = 3”
Hilo 4 llama update,
Hilo 4: “count = 4”
.
.
}
}
}
17
Multiples Clientes “Concurrentes”
18
Paradigma Cliente Servidor
Multiples Cliente – Un Servidor
Servidor sin conexión:
Hilo 1 atiende A
t=1. A puja 50E por BMW
Hilo 2 atiende B
H1 H2
Usa IPC sin conexión (p.ej., datagram socket)
Las sesiones con clientes concurrentes se pueden
intercalar.
Hilo 3 atiende C
H3
Servidor con conexión:
t=1. B puja 60E por BMW
eBay
Server
Usa IPC con conexión (p.ej. stream-mode socket )
Sesiones con clientes concurrentes solo pueden ser
secuenciales.
Concurrencia necesita servidor multitarea.
t=1. C Lee Puja Actual de BMW.
19
20
Sesiones de clientes concurrentes con
servidor sin conexión
EchoServer1
client 1
Servidor con Sockets sin conexión
public class EchoServer1 {
public static void main(String[] args) {
…
// instantiates a datagram socket for both sending and
receiving data
MyServerDatagramSocket mySocket = new
MyServerDatagramSocket(serverPort);
while (true) { // forever loop
DatagramMessage request =
mySocket.receiveMessageAndSender();
String msg = request.getMessage( );
mySocket.sendMessage(request.getAddress( ),
request.getPort( ), msg);
} //end while
}
client2
message
echo
message
echo
message
echo
message
echo
message
echo
21
Servidores Iterativos (socket con conexión)
Sesiones cliente consecutivas.
EchoServer2
Client 1
Bucle
Bucle
= Sesión
Servidor
cliente.
public class MyServerDatagramSocket extends DatagramSocket {
MyServerDatagramSocket(int portNo) throws SocketException{
super(portNo);
}
public void sendMessage(InetAddress receiverHost, int receiverPort,
string message);
public String receiveMessage( );
public DatagramMessage receiveMessageAndSender( );
} //end class
22
Servidor Iterativo (socket con conexión)
public class EchoServer2 {
public static void main(String[] args) {
Client 2
Message 1a
ServerSocket myConnectionSocket = new ServerSocket(serverPort);
while (true) { // forever loop
MyStreamSocket myDataSocket = new MyStreamSocket
(myConnectionSocket.accept( ));
boolean done = false;
while (!done) {
message = myDataSocket.receiveMessage( );
if ((message.trim()).equals (endMessage)) {
myDataSocket.close( );
done = true;
} //end if
else {
myDataSocket.sendMessage(message);
} //end else
} //end while !done
} //end while forever
Echo 1a
Message 2a
Message 1b
Echo 1b
Message .
Echo 2a
Message 2b
Echo 2b
23
Bucle
servidor.
Bucle
sesión
cliente.
24
Servidor concurrente:
sesiones concurrentes
Sequence diagram – EchoServer3
EchoServer3
accept
EchoServer3
client 1
message
echo
message
echo
client2
accept
EchoClient
1
EchoClient2
EchoServer3
thread 1
EchoServer3
thread 2
message
echo
message
echo
message
echo
25
26
Servidor MultiHilo
Hilo Atiende un Cliente
import java.io.*;
import java.net.*;
public class EchoServer3 {
public static void main(String[] args) {
int serverPort = 7;
// default port
String message;
try {
// instantiates a stream socket for accepting
//
connections
ServerSocket myConnectionSocket =
new ServerSocket(serverPort);
while (true) { // forever loop
// wait to accept a connection
MyStreamSocket myDataSocket = new MyStreamSocket
(myConnectionSocket.accept( ));
// Start a thread to handle this client's sesson
Thread theThread = new Thread(new
EchoServerThread(myDataSocket));
theThread.start();
} //end while forever
} // end try
catch (Exception ex) {
Cliente
ex.printStackTrace( );
} // end catch
} //end main
} // end class
import java.io.*;
class EchoServerThread implements Runnable {
static final String endMessage = ".";
MyStreamSocket myDataSocket;
EchoServerThread(MyStreamSocket myDataSocket) {
this.myDataSocket = myDataSocket;
}
public void run( ) {
boolean done = false;
String message;
try {
while (!done) {
message = myDataSocket.receiveMessage( );
if ((message.trim()).equals (endMessage)){
myDataSocket.close( );
done = true;
} //end if
else {
myDataSocket.sendMessage(message);
} //end else
} //end while !done
}// end try
Cliente
catch (Exception ex) {
System.out.println("Exception " + ex);
} // end catch
} //end run
} //end class
Por cada cliente:
•Nuevo thread,
•Start thread.
Hilo2
Hilo1
Server
Thread
new Thread()
Thread.start()
Server
JVM
PID3
27
•Constructor recibe un
DataSocket.
•El código en run() se
ejecuta para cada
petición.
Hilo2
Hilo1
run()
ServerThread
Server
JVM
PID3
28
Descargar