Java - Hilos Synchronized Java

 
Vista:

Hilos Synchronized Java

Publicado por Gabilondo (3 intervenciones) el 05/12/2018 03:51:38
Buenas noches tengo un ejercicio que consiste en un esquema productor/consumidor. El programa consiste en crear dos hilos. Uno de ellos producirá y el otro consumirá.

El productor irá insertando números en orden (1,2,3...) en un buffer circular con capacidad para 4 datos. Hay que sincronizar los dos hilo de manera que el productor vaya produciendo según he dicho, y el consumidor los vaya leyendo.

Si el buffer está lleno pondrá el hilo productor en wait() y si está vacio el hilo consumidor en wait().

Lo que ocurre es que cuando lo ejecuto a veces el consumidor se salta una vuelta completa de buffer o vuelve algún numero atrás.

La clase main:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Main implements Runnable{
	public Main() {
 
	}
 
	@Override
	public void run() {
 
	}
 
		public static void main(String[] args) {
			CircularBuffer cb=new CircularBuffer(4);
				Productor p=new Productor(cb);
				p.start();
			//Creo una pausa para que empieze el productor con ventaja
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			Consumidor c=new Consumidor(cb);
			c.start();
 
 
		}
}

La clase productor :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Productor extends Thread{
	 	CircularBuffer cb;
	    public Productor(CircularBuffer cb)
	    {
	    	this.cb=cb;
	    }
 
	    @Override
	    public void  run() {
	    	int i=1;
	        while(!cb.finalizado()) {
	        	try {
	    			Thread.sleep((long)(Math.random()*2000));
	    		} catch (InterruptedException e1) {
	    			// TODO Auto-generated catch block
	    			e1.printStackTrace();
	    		}
	        		cb.producir(i);
	        		System.out.println("Productor: "+i);
	        		i++;
	        }
	    }
}

La clase consumidor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Consumidor extends Thread{
	CircularBuffer cb;
    public Consumidor(CircularBuffer cb)
    {
    	this.cb=cb;
    }
 
    @Override
    public void run() {
    	int num=0;
        while(!cb.finalizado()) {
        	 try {
 				Thread.sleep((long)(Math.random()*2000));
 			} catch (InterruptedException e1) {
 				// TODO Auto-generated catch block
 				e1.printStackTrace();
 			}
        		num=cb.consumir();
        		System.out.println("Consumidor: "+num);
        }
    }
}

Y la clase CircularBuffer:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
class CircularBuffer {
	  private Integer array[];
	  private int guardar;
	  private int leer;
	  private boolean finalizado;
 
	  public CircularBuffer(Integer number) {
	    array = new Integer[number];
	    guardar = 0;
	    leer = 0;
	    finalizado=false;
	  }
 
	  public synchronized void producir(Integer value) {
 
		  if(bufferFull()) {
			  System.out.println("Esperando, buffer lleno...");
			  try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			  array[guardar] = value;
		      if (guardar == array.length-1) {
		        guardar = 0;
		      }
		      guardar++;
		  }else {
			  array[guardar] = value;
		      if (guardar == array.length-1) {
		        guardar = 0;
		      }
		      guardar++;
		  }
		  notifyAll();
	  }
 
	  public synchronized Integer consumir() {
 
	    if (bufferEmpty() && leer!=guardar) {
	    	System.out.println("Esperando, buffer vacío...");
	    	try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
	    	int value = array[leer];
	      if (leer == array.length-1) {
	        leer = 0;
	      }
	      leer++;
	      notifyAll();
	      return value;
	    } else {
	    	  int value = array[leer];
		      if (leer == array.length-1) {
		    	  leer = 0;
		      }
		      leer++;
		      notifyAll();
		      return value;
	    }
	  }
 
	  private boolean bufferEmpty() {
	    if (leer + 1 == guardar) {
	      return true;
	    }
	    if (leer == (array.length-1) && guardar == 0) {
	      return true;
	    }
	    return false;
	  }
	  private boolean bufferFull() {
		    if (guardar + 1 == leer) {
		      return true;
		    }
		    if(guardar ==(array.length-1) && leer==0) {
		    	return true;
		    }
		    return false;
		  }
	  public boolean finalizado() {
		  return finalizado;
	  }
 
 
}

Gracias de antemano.
Un saludo.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Hilos Synchronized Java

Publicado por Tom (1697 intervenciones) el 06/12/2018 12:27:26
¿ Necesitas un buffer circular para eso ? Teniendo en cuenta que el productor se para cuando el buffer está lleno, no le veo la necesidad.
Por otra parte, debes concretar más. Eso de "a veces" significa que hay que gastar tiempo con el debuger hasta ver cuando falla. En mi opinión, ese tiempo deberías gastarlo tú mismo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Hilos Synchronized Java

Publicado por Gabilongo (3 intervenciones) el 06/12/2018 17:23:50
No me da error ninguno. Solo ocurre lo que comento, se salta una vuelta de Buffer y sigue ejecutandose con normalidad. Supongo que el error se produce en consumir(), ya que al imprimir los valores al producir nunca se salta valor alguno. Pero tras mirarlo muchas veces y probar algo nuevo sigue ocurriendo lo mismo, no sé a que se puede deber.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Hilos Synchronized Java

Publicado por Gabilondo (3 intervenciones) el 06/12/2018 18:29:39
Ya encontré el error. Era que acto seguido de reestablecer a 0 el Buffer (cuando llegaba a su posicion máxima) sumaba 1. Entonces nunca llegaba a la posición 0 del array y por eso no me ejecutaba bien el resto del código. Un saludo, y gracias por la atención.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar