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!