Foros del Web » Programación para mayores de 30 ;) » Java »

Duda con Ejercicio Multi Hilo

Estas en el tema de Duda con Ejercicio Multi Hilo en el foro de Java en Foros del Web. Buenos dias, tengo que hacer este ejercicio: "Realizar un programa en el que vamos a tener un array dinamico que se vacia y llena constantemente ...
  #1 (permalink)  
Antiguo 14/11/2015, 05:31
 
Fecha de Ingreso: febrero-2015
Mensajes: 12
Antigüedad: 9 años, 9 meses
Puntos: 0
Duda con Ejercicio Multi Hilo

Buenos dias, tengo que hacer este ejercicio:

"Realizar un programa en el que vamos a tener un array dinamico que se vacia y llena constantemente con un numero determinado de elementos (por ejemplo 10). Los encargados del vaciado y llenado van a ser dos hilos, uno que se encarga de llenar y otro de vaciar continuamente. Por defecto el array estara vacio".

Yo he hecho esto:

Clase ArrayDinamico:

Código:
public class ArrayDinamico
{
    protected static ArrayList<Integer> lista;
    protected int numElementos;
    protected  boolean estaLleno;

    public ArrayDinamico(int numElementos)
    {
        this.numElementos = numElementos;
        estaLleno = false;
        lista = new ArrayList<>(numElementos);
    }

    public boolean isEstaLleno()
    {
        return estaLleno;
    }

    public synchronized void llenarArray()
    {
        if (lista.isEmpty())
        {
            for (int i = 0; i < numElementos; i++)
            {
                lista.add((int) (Math.random() * 100) + 1);
            }
            for (int num : lista)
            {
                System.out.print(num + " ");
            }
            System.out.println("ARRAY LLENO");
            estaLleno = true;
            try
            {
                Thread.sleep(300);
            } catch (InterruptedException e)
            {

            }
            notifyAll();
        }
    }

    public synchronized void vaciarArray()
    {
        if (lista.size() == numElementos)
        {
            System.out.println("VACIANDO ARRAY");
            for (int i = lista.size(); i == 0; i--)
            {
                lista.remove(i);
            }
            System.out.println("ARRAY VACIO");
            estaLleno = false;
            try
            {
                Thread.sleep(300);
            } catch (InterruptedException e)
            {

            }
        }
        else
        {
            try
            {
                System.out.println("WAIT!");
                wait();
            } catch (InterruptedException e)
            {

            }
        }
    }



}
Clase Llenar
Código:
public class Llenar extends Thread
{
    ArrayDinamico arrayDinamico;

    public Llenar(ArrayDinamico arrayDinamico)
    {
        this.arrayDinamico = arrayDinamico;
    }

    @Override
    public void run()
    {
        if (!arrayDinamico.isEstaLleno())
        {
            arrayDinamico.llenarArray();
        }
    }


}
Clase vaciar
Código:
public class Vaciar extends Thread
{
    ArrayDinamico arrayDinamico;

    public Vaciar(ArrayDinamico arrayDinamico)
    {
        this.arrayDinamico = arrayDinamico;
    }

    @Override
    public void run()
    {
        if (arrayDinamico.estaLleno)
        {
            arrayDinamico.vaciarArray();
        }
    }

}
public class PruebaArray
{
public static void main(String[] args)
{
ArrayDinamico a1 = new ArrayDinamico(10);
Llenar llenar = new Llenar(a1);
Vaciar vaciar = new Vaciar(a1);

llenar.start();
vaciar.start();
}
}


Pero no tengo el resultado esperado. El metodo vaciarArray nunca llega a ejecutarse. El programa solo imprime esto:

11 85 97 30 42 76 63 66 9 62 ARRAY LLENO

Alguien me echa un cable? Gracias!
  #2 (permalink)  
Antiguo 16/11/2015, 10:40
 
Fecha de Ingreso: noviembre-2015
Mensajes: 34
Antigüedad: 9 años
Puntos: 4
Respuesta: Duda con Ejercicio Multi Hilo

Creo ver tu problema, en el main ejecutas llenar y vaciar al mismo tiempo(bueno, no exactamente al mismo tiempo, pero prácticamente si), entonces el Thread vaciar se ejecuta cuando aún el ArrayDinámico no está lleno, en ese punto se me ocurren dos cosas para arreglarlo, la más fácil y sencilla es hacer que el Thread vaciar espere medio o 1 segundo antes de vaciarlo con sleep(1000) antes de empezar nada, ahora bien, según el enunciado de tu ejercicio, tiene que estar constantemente llenándose y vaciándose y con eso solo lo haría una vez, una vez el método run se ejecute con start() y haya terminado el proceso habrá muerto, y en el caso de volverlos a crear y ejecutarlos muchas veces(o infinitamente), el sleep(1000) ya no es fiable porque no necesariamente los dos procesos tardan lo mismo y llegará un punto en el que el Thread vaciar vuelva a intentar vaciarlo sin estar lleno, ahora bien, entonces como es posible que llene y vacie consecutivamente sin cagarla? la respuesta está en hacer llamadas recursivas, cuando el llenar acabe, debe ser él quien llame a vaciar, cuando vaciar acabe, él debe llamar a llenar, no se si se entiende, asi que voy a lo práctico:

Código:
public class Llenar extends Thread
{
    ArrayDinamico arrayDinamico;

    public Llenar(ArrayDinamico arrayDinamico)
    {
        this.arrayDinamico = arrayDinamico;
        
    }

    @Override
    public void run()
    {
        if (!arrayDinamico.isEstaLleno())
        {
            arrayDinamico.llenarArray();
            Vaciar vaciar = new vaciar(this.arrayDinamico); //no puedes revivir un Thread muerto, asi que creamos una nuevo cada vez
            vaciar.start(); //cuando terminemos de llenarlo debemos vaciarlo

        }
    }


}
Código:
public class Vaciar extends Thread
{
    ArrayDinamico arrayDinamico;

    public Vaciar(ArrayDinamico arrayDinamico)
    {
        this.arrayDinamico = arrayDinamico;
    }

    @Override
    public void run()
    {
        if (arrayDinamico.estaLleno)
        {
            arrayDinamico.vaciarArray();
            Llenar llenar = new Llenar(arrayDinamico);//lo mismo de antes
            llenar.start(); //cuando vaciamos volvemos a llenar
        }
    }

}
Con esto consigues llamadas recursivas infinitas(tu ejercicio dice que debe hacerlo constantemente, es decir siempre XD) y te aseguras de que un thread no va ejecutar un método hasta que se haya ejecutado el otro, así pues en el main solo debes iniciar el Llenar que se debe hacer primero.

Código:
public class PruebaArray
 {
 public static void main(String[] args)
 {
 ArrayDinamico a1 = new ArrayDinamico(10);
 Llenar llenar = new Llenar(a1);
 llenar.start();
 
 }
 }
En el caso de que quieras pararlo en algún momento, deberías buscar alguna condición o un evento(de una aplicación de escritorio por ejemplo) que cuando se cumpla puedas ejecutar llenar.stop() y vaciar.stop() (Sí, lo sé, stop() está obsoleto, pero es la manera más simple y sin lios y más si estás aprendiendo).

Espero que te haya ayudado y servido, saludos!

Etiquetas: clase, ejercicio, hilo, metodo, multi, programa, string
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 14:38.