sábado
oct292011
Ejemplo de hilos 2.
001.
package
es.scjp;
002.
003.
import
java.util.Vector;
004.
005.
/**
006.
* En esta clase vamos a intentar sincronizar dos hilos y un recurso entre sí
007.
* La idea es generar un productor y un consumidor que produzcan y lean elementos
008.
* @author jcarmonaloeches
009.
* @desarrolloj2ee (twitter)
010.
*/
011.
public
class
HilosEnJavaParte2 {
012.
013.
public
static
void
main(String args[]) {
014.
/*Recurso que compartiremos entre el productor y el consumidor*/
015.
RecursoCompartido rc =
new
RecursoCompartido();
016.
/*Creamos la instancia de productor y consumidor, esta instancia recibe el parámetro del recurso compartido*/
017.
Productor productor =
new
Productor(rc);
018.
Consumidor consumidor =
new
Consumidor(rc);
019.
/*Iniciamos el productor y el consumidor. Esta llámada ejecuta el método run*/
020.
productor.start();
021.
consumidor.start();
022.
023.
try
{
024.
Thread.sleep(
5000
);
025.
}
catch
(InterruptedException e) {
026.
// TODO Auto-generated catch block
027.
e.printStackTrace();
028.
}
029.
/*Damos la orden a los threads indicando que ya no están activos*/
030.
productor.setEstaActivo(
false
);
031.
consumidor.setEstaActivo(
false
);
032.
}
033.
}
034.
035.
/**
036.
* Hilo productor que inserta datos de manera sincronizada en un recurso compartido.
037.
* La variables estaActivo indica si el hilo está en ejecución.
038.
* @author Jaime Carmona Loeches
039.
* @desarrolloj2ee (twitter)
040.
*/
041.
class
Productor
extends
Thread {
042.
043.
private
boolean
estaActivo =
true
;
044.
private
RecursoCompartido rc;
045.
046.
public
boolean
isEstaActivo() {
047.
return
estaActivo;
048.
}
049.
050.
public
void
setEstaActivo(
boolean
estaActivo) {
051.
this
.estaActivo = estaActivo;
052.
}
053.
054.
public
Productor(RecursoCompartido rc) {
055.
this
.rc = rc;
056.
}
057.
058.
public
void
run() {
059.
while
(estaActivo) {
060.
rc.añadirDatos();
061.
}
062.
}
063.
}
064.
065.
/**
066.
* Hilo que recibe datos de un recurso compartido de manera sincronizada
067.
*
068.
* @author Jaime Carmona Loeches
069.
* @desarrolloj2ee (twitter)
070.
*
071.
*/
072.
class
Consumidor
extends
Thread {
073.
private
boolean
estaActivo =
true
;
074.
private
RecursoCompartido rc;
075.
076.
public
Consumidor(RecursoCompartido rc) {
077.
this
.rc = rc;
078.
}
079.
080.
public
boolean
isEstaActivo() {
081.
return
estaActivo;
082.
}
083.
084.
public
void
setEstaActivo(
boolean
estaActivo) {
085.
this
.estaActivo = estaActivo;
086.
}
087.
088.
public
void
run() {
089.
while
(estaActivo) {
090.
rc.leerDatos();
091.
}
092.
}
093.
}
094.
095.
/**
096.
* Clase que permite gestionar un recurso. El estado indica 1 o 2, es decir,
097.
* leyendo o añadiendo. Los métodos se ejecutan de manera complementaria: o bien
098.
* ejecuta uno, o bien ejecuta otro. Al ser métodos sincronizados, un método
099.
* sólo puede ser ejecutado por un mismo hilo a la vez. Cuando un método termina
100.
* la ejecución indicará a los hilos la finalización de esta ejecución, y eso
101.
* permitirá saltar del estado wait al estado run.
102.
*
103.
* @author Jaime Carmona Loeches
104.
* @desarrolloj2ee
105.
*/
106.
class
RecursoCompartido {
107.
private
int
estado =
2
;
108.
private
int
contador =
0
;
109.
private
Vector recursoCompartido =
new
Vector();
110.
111.
public
Vector getRecursoCompartido() {
112.
return
recursoCompartido;
113.
}
114.
115.
public
void
setRecursoCompartido(Vector recursoCompartido) {
116.
this
.recursoCompartido = recursoCompartido;
117.
}
118.
119.
/**
120.
* Metodo de añadido de datos, estado = 2
121.
* Este método es sincronizado y no permite que dos hilos lo ejecuten a la vez.
122.
* En caso de que haya dos hilos que quieran ejecutar, la JVM
123.
* establece prioridades de ejecución, estableciendo una cola de espera
124.
*/
125.
public
synchronized
void
añadirDatos() {
126.
/*Mientras el estado sea igual a 2, se establece una espera, que terminará
127.
cuando el estado cambie de valor*/
128.
while
(estado ==
2
) {
129.
try
{
130.
wait();
131.
}
catch
(InterruptedException e) {
132.
// TODO Auto-generated catch block
133.
e.printStackTrace();
134.
}
135.
}
136.
137.
/**
138.
* Cuando el estado cambia de valor, leemos los elementos e imprimimos la información
139.
*/
140.
StringBuffer elementosLeidos =
new
StringBuffer();
141.
while
(recursoCompartido.size() >
0
) {
142.
elementosLeidos.append(
"*"
+recursoCompartido.firstElement());
143.
recursoCompartido.remove(
0
);
144.
}
145.
146.
System.out.println(
"Consumido->"
+ elementosLeidos +
"*"
);
147.
/*Finalmente, modificamos el estados, y mediante notifyAll, notificamos al resto de hilos que esperaban a este método que esta ejecución ha finalizado*/
148.
estado =
2
;
149.
notifyAll();
150.
}
151.
152.
/**
153.
* Metodo de lectura de datos, estado = 1
154.
*/
155.
public
synchronized
void
leerDatos() {
156.
while
(estado ==
1
) {
157.
try
{
158.
wait();
159.
}
catch
(InterruptedException e) {
160.
// TODO Auto-generated catch block
161.
e.printStackTrace();
162.
}
163.
}
164.
165.
/**
166.
* Añadimos 5 elementos y mantenemos la cuenta a nivel de instancia de
167.
* clase
168.
*/
169.
StringBuffer elementosGenerados =
new
StringBuffer();
170.
int
valorFinal = contador +
5
;
171.
for
(
int
i = contador; i < valorFinal; i++, contador++) {
172.
String numero =
new
Integer(i).toString();
173.
elementosGenerados.append(
"*"
+ numero);
174.
this
.getRecursoCompartido().add(numero);
175.
}
176.
elementosGenerados.append(
"*"
);
177.
System.out.println(
"Producido->"
+ elementosGenerados);
178.
estado =
1
;
179.
notifyAll();
180.
}
181.
}
Reader Comments