viernes, 4 de abril de 2014

Ejercicios Básicos de Concurrencia en Java (Parte 1/3)

Buenas gente. Hoy os traigo ejercicios de lo más básico para practicar la concurrencia en Java.
Aquí os dejo el enunciado de los dos primeros:

1. Realizar un programa en Java con 3 hebras, cada una de las cuales escribe por
pantalla varias veces (valor pasado como parámetro en el constructor) el carácter
que se le indique (también indicado como parámetro). ¿Se mezclan las letras?
Justifica el comportamiento observado.

b) Modificar el programa de la siguiente manera: se van a mostrar las letras A, B
y C. Para ello, utilizaremos 3 hebras como en el caso anterior, pero queremos
limitar la posible salida de caracteres por pantalla para que no se produzca de
cualquier forma sino con la secuencia indefinida: ABBCCC, esto es, por
ejemplo: ABBCCCABBCCCABBCCC...

Se recomienda la utilización de una variable compartida por las hebras que sirva
para asignar turnos, de manera que cada hebra imprime su letra cuando sea su
turno. De esta forma, cuando se crean las hebras, a cada una se le asigna un
identificador para que puedan comprobar cuando es su turno, y que mientras no
sea su turno, no hagan nada (ej: while (turno != miid) ; )

2. Disponemos de una clase denominada VariableCompartida que encapsula el
valor de una variable v de tipo int. La clase VariableCompartida contiene
métodos para establecer (método set), obtener (método get) o incrementar
(método inc) el valor de v. Realizar un programa en Java que cree 2 hebras
compartiendo una instancia de la clase VariableCompartida e incrementen
cada una de ella 10 veces el valor de v. Mostrar desde la hebra del programa
principal el valor final de v. ¿Se obtienen los resultados esperados? Aumenta
progresivamente el número de incrementos hasta observar algún
comportamiento “extraño”. Justifica los resultados obtenidos. 
Y aquí os dejo los resultados ;)

Primer Ejercicio:

   public class EscribirCaracter extends Thread {
        public volatile static int turno; 
 //static hace que el valor sea el mismo en todos los objetos
 //volatile hace que la variable turno sea compartida entre varias hebras
 private int veces;
 private char car;
 private int id;
 
 public EscribirCaracter(int v, char c, int i) {
  turno = 0;
  veces = v;
  car = c;
  id = i;
 }
 
 public void run() {
  while(turno!=id);
   for(int k = 0; k < veces; k++) {
    System.out.print(car);
   }
  
  turno = (turno+1)%3;
 }
 
 public static void main(String[] args) throws InterruptedException {
  EscribirCaracter h1, h2, h3;
  h1 = new EscribirCaracter(1, 'A', 0);
  h2 = new EscribirCaracter(2, 'B', 1);
  h3 = new EscribirCaracter(3, 'C', 2);
 
  h1.start();
  h2.start();
  h3.start();
  try {
   h1.join();
   h2.join();
   h3.join();
  } catch(InterruptedException e) {
   throw new InterruptedException();
  }
  
  
 }
}

Segundo ejercicio:

public class Incrementador extends Thread{
 
 private int vueltas;
 private VariableCompartida var;
 
 public Incrementador(int i, VariableCompartida v) {
  vueltas = i;
  var = v;
 }
 
 public void run() {
  for(int i = 0; i < vueltas; i++) {
   var.inc();
  }
 }
 
 
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  VariableCompartida variable = new VariableCompartida(0);
  Incrementador i1 = new Incrementador(1000, variable);
  Incrementador i2 = new Incrementador(1000, variable);
  
  i1.start();
  i2.start();
  
  try {
   i1.join();
   i2.join();
  } catch(InterruptedException e) {
   e.printStackTrace();
   
  }
  
  System.out.println(variable.get());
  
 }

}

Y la class VariableCompartida que es:

public class VariableCompartida {
 public static volatile int turno = 0;
 private int var;
 public VariableCompartida(int i) {
  var = i;
 }
 
 public void set(int i) {
  var = i;
 }
 public int get() {
  return var;
 }
 public void inc() {
  var++;
 }
 public static void incTurno() {
  turno = (turno+1)%2;
 }
 public static int getTurno() {
  return turno;
 }
}

Espero que hayais estado un rato entretenidos con los ejercicios. Estoy preparando otros más para subir :)

Saludos;)

2 comentarios:

  1. public void run() {
    while(turno!=id); <--------------------------------------
    for(int k = 0; k < veces; k++) {
    System.out.print(car);
    }

    turno = (turno+1)%3;
    }



    ¿Puedes explicarme qué hace ese while? No se como puede funcionar un while sin cuerpo como se ve ahí, o es una forma especial para ejecutar algo que no se.

    ResponderEliminar
    Respuestas
    1. Recordemos que estamos trabajando en concurrencia. Ésto significa que coexisten varios métodos run() "a la vez" (en realidad se van alternando pero por no liarlo más...

      Ese while lo que hace se llama "Espera Activa" y es algo poco aconsejable en proyectos más avanzados, pero que para aprender nos vale.

      Se trata de valorar que mientras valor no valga lo que id, el while va a seguir ejecutandose (aunque no haga nada, es como un bucle infinito). Pero seguro que hay otro run() cuyo id sea igual a valor. Entonces lo que hará será ejecutarlos en orden. No se si me explico bien del todo. Busca información en Google sobre espera activa a ver si te ayuda ;)

      Saludos;)

      Eliminar