inactividad el subproceso actual en ejecución durante un máximo de 4 milisegundos. En breve hablaremos sobre
el por qué de esto. En la línea 61 se evalúa si el elemento del arreglo
primos
en el índice actual es
true
(y por
ende, primo). De ser así, en la línea 63 se pasa el índice al método
publish
de manera que pueda mostrarse como
resultado intermedio en la GUI, y en la línea 64 se incrementa el número de primos encontrados. En las líneas 66
y 67 se establecen en
false
todos los múltiplos del índice actual, para indicar que no son primos. Cuando se ha
recorrido todo el arreglo
boolean
, el número de primos encontrados se devuelve en la línea 72.
En las líneas 76 a 80 se declara el método
process
, el cual se ejecuta en el subproceso de despachamiento
de eventos y recibe su argumento
valsPublicados
del método
publish
. El paso de valores entre
publish
en
el subproceso trabajador y
process
en el subproceso de despachamiento de eventos es asíncrono;
process
no se
invoca necesariamente para cada una de las llamadas a
publish
. Todos los objetos
Integer
publicados desde la
última llamada a
publish
se reciben como un objeto
List
, a través del método
process
. En las líneas 78 y 79
se itera a través de esta lista y se muestran los valores publicados en un objeto
JTextArea
. Como el cálculo en el
método
doInBackground
progresa rápidamente, publicando valores con frecuencia, las actualizaciones al objeto
JTextArea
se pueden apilar en el subproceso de despachamiento de eventos, lo que puede provocar que la GUI
tenga una respuesta lenta. De hecho, al buscar un número sufi cientemente largo de primos, el subproceso de
despachamiento de eventos puede llegar a recibir tantas peticiones en una rápida sucesión para actualizar el objeto
JTextArea
, que el subproceso se quedará sin memoria en su cola de eventos. Ésta es la razón por la cual pusi-
mos al subproceso trabajador en inactividad durante unos cuantos milisegundos, entre cada llamada potencial a
publish
. Se reduce la velocidad del cálculo lo sufi ciente como para permitir que el subproceso despachador de
eventos se mantenga a la par con las peticiones para actualizar el objeto
JTextArea
con nuevos números primos,
lo cual permite a la GUI actualizarse de manera uniforme y así puede permanecer con una capacidad de respuesta
relativamente inmediata.
En las líneas 83 a 106 se defi ne el método
done
. Cuando el cálculo termina o se cancela, el método
done
habilita el botón
Obtener primos
y deshabilita el botón
Cancelar
(líneas 85 y 86). En la línea 92 se obtiene el
valor de retorno (el número de primos encontrados) del método
doInBackground
. En las líneas 94 a 103 se
atrapan las excepciones lanzadas por el método
get
y se muestra un mensaje de error apropiado en el objeto
estadoJLabel
. Si no ocurren excepciones, en la línea 105 se establece el objeto
estadoJLabel
para indicar el
número de primos encontrados.
En las líneas 109 a 112 se defi ne el método
publicdetenerCalculo
, el cual se invoca cuando el usua-
rio hace clic en el botón
Cancelar
. Este método establece la bandera
detenido
en la línea 111, de forma que
doInBackground
pueda regresar sin terminar su cálculo la próxima vez que evalúe esta bandera. Aunque
Swing-
Worker
cuenta con un método
cancel
, este método simplemente llama al método
interrupt
de
Thread
en el
subproceso trabajador. Al utilizar la bandera
boolean
en vez del método
cancel
, podemos detener el cálculo
limpiamente, devolver un valor de
doInBackground
y asegurar que se haga una llamada al método
done
, aun si
el cálculo no se ejecutó hasta completarse, sin el riesgo de lanzar una excepción
InterruptedException
asociada
con la acción de interrumpir el subproceso trabajador.
La clase
BuscarPrimos
(fi gura 23.28) muestra un objeto
JTextField
que permite al usuario escribir un
número, un objeto
JButton
para empezar a buscar todos los números primos menores que ese número, y
un objeto
JTextArea
para mostrar los números primos. Un objeto
JButton
permite al usuario cancelar el cálcu-
lo, y un objeto
JProgressBar
indica el progreso del cálculo. El constructor de
BuscarPrimos
(líneas 32 a 125)
inicializa estos componentes y los muestra en un objeto
JFrame
, usando el esquema
BorderLayout
.
En las líneas 42 a 94 se registra el manejador de eventos para el objeto
obtenerPrimosJButton
. Cuando el
usuario hace clic en este objeto
JButton
, en las líneas 47 a 49 se restablece el objeto
JProgressBar
y se borran los
objetos
mostrarPrimosJTextArea
y
estadoJLabel
. En las líneas 53 a 63 se analiza el valor en el objeto
Jtext-
Field
y se muestra un mensaje de error si el valor no es un entero. En las líneas 66 a 68 se construye un nuevo
objeto
CalculadoraPrimos
, el cual recibe como argumentos el entero que escribió el usuario, el objeto
mos-
trarPrimosJTextArea
para mostrar los números primos, el objeto
estadoJLabel
y los dos objetos
JButton
.
En las líneas 71 a 85 se registra un objeto
PropertyChangeListener
para el nuevo objeto
Calculadora-
Primos
, mediante el uso de una clase interna anónima.
PropertyChangeListener
es una interfaz del paquete
java.beans
que defi ne un solo método,
propertyChange
. Cada vez que se invoca el método
setProgress
en
un objeto
CalculadoraPrimos
, este objeto genera un evento
PropertyChangeEvent
para indicar que la pro-
piedad de progreso ha cambiado. El método
propertyChange
escucha estos eventos. En la línea 78 se evalúa si
un evento
PropertyChangeEvent
dado indica un cambio en la propiedad de progreso. De ser así, en la línea 80
se obtiene el nuevo valor de la propiedad y en la línea 81 se actualiza el objeto
JProgressBar
con el nuevo valor
23.11 Subprocesamiento múltiple con GUIs
979
23_MAQ_CAP_23_DEITEL.indd979
4/19/081:34:00AM