que - swingworker java ejemplo
Ejecutar el proceso en Java sin congelar JFrame (3)
¿cómo puedo ejecutar un proceso en Java sin congelar el programa? Intenté usar SwingWorker, pero todavía no entiendo cómo funciona.
¿Hay alguna otra forma en que pueda lograr esto? Quiero usar algo como esto en mi JDroidLib. Para obtener el código fuente completo, consulte el GitHub: http://github.com/Team-M4gkBeatz/JDroidLib
¡Gracias por adelantado!
EDITAR:
Gracias por tus respuestas. Pero tengo una clase con varios métodos (bueno, es más de una clase, pero entiendes mi punto); ¿cómo puedo usar un SwingWorker para interactuar con ellos?
Aquí está una de las clases:
/**
*
* @author Simon
*/
public abstract class Command extends SwingWorker {
BufferedReader prReader = null;
ProcessBuilder process = null;
Process pr = null;
Date timeNow = new Date();
String osName = System.getProperty("os.name");
public void executeProcessNoReturn(String _process, String arg) throws IOException {
process = new ProcessBuilder(_process, arg);
pr = process.start();
}
public String executeProcessReturnLastLine(String _process, String arg) throws IOException {
process = new ProcessBuilder(_process, arg);
pr = process.start();
prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line;
while ((line = prReader.readLine()) != null) {
// Wait for input to end.
}
return line;
}
public StringBuilder executeProcessReturnAllOutput(String _process, String arg) throws IOException {
process = new ProcessBuilder(_process, arg);
pr = process.start();
prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
StringBuilder output = null;
String line;
while ((line = prReader.readLine()) != null) {
output.append(line);
}
return output;
}
public boolean isProcessRunning(String processName) throws IOException {
boolean value = false;
if (osName.equals("Linux") | osName.contains("Mac")) {
process = new ProcessBuilder("ps", "-e");
pr = process.start();
String line;
prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line = prReader.readLine()) != null) {
if (line.contains(processName)) { value = true; break; }
}
} else {
String winDir = System.getenv("windir") + "/System32/tasklist.exe";
process = new ProcessBuilder(winDir);
pr = process.start();
String line;
prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line = prReader.readLine()) != null) {
if (line.contains(processName)) { value = true; break; }
}
}
return value;
}
public String executeProcessReturnError(String processName, String arg) throws IOException {
process = new ProcessBuilder(processName, arg);
process.redirectError();
pr = process.start();
prReader = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
String line;
String output = "";
while ((line = prReader.readLine()) != null) {
output += line + "/n";
}
return output;
}
}
Necesita ejecutar el código en un subproceso separado. La palabra clave para ejecutar y coordinar múltiples rutas de código en un programa es "concurrencia":
http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
El código multiproceso puede ser bastante difícil y difícil de depurar, pero Java proporciona algunas abstracciones / conceptos de nivel superior que hacen que trabajar con código multiproceso sea menos propenso a errores.
Eche un vistazo al paquete java.util.concurrent para estos conceptos.
Debido a que el multihilo es un problema que seguramente se encontrará cuando trabaje con AWT / Swing, existen algunas clases / métodos de utilidad especialmente diseñados para facilitar el multihilo en aplicaciones gráficas. SwingWorker es uno de ellos (otro es, por ejemplo, SwingUtilities.invokeLater () ). Sería una buena idea familiarizarse con ellos, pueden hacer su vida más fácil, especialmente para tareas simples que son lo suficientemente largas como para congelar la GUI.
Si está utilizando Swing, SwingWorker es la manera de hacerlo.
Como has mencionado que no entiendes cómo funciona, daré una explicación simple.
El código de manejo de eventos Swing se realiza en el hilo de envío del evento . Por lo tanto, si un usuario hace clic en un botón (por ejemplo, el botón de actualización que obtiene los datos del servidor y los muestra en la ventana), se llama al ActionListener de ese botón en la cadena de distribución del evento.
Si busca los datos en el mismo hilo, la IU se congelaría, porque no puede procesar ningún evento (está ejecutando código en el hilo de envío del evento).
Por lo tanto, debe buscar los datos en un hilo separado. Pero después de obtener los datos, debe configurarlos en la vista en el hilo de envío del evento.
El trabajador de Swing lo hace fácil para ti. doInBackground
la tarea pesada en el método doInBackground
(en nuestro caso recuperando los datos) y devuelve el resultado de la tarea pesada (en nuestro caso, los datos) del método.
En el método done
del trabajador de swing llama al método get
que le dará los datos devueltos en el método doInBackground
. Allí, actualiza la vista con los datos nuevos (por ejemplo, agrega los datos a un modelo de tabla).
Cuando llame a exectue
en su trabajador de swing ahora, se encargará de ejecutar doInBackground
en un subproceso separado (que no es el subproceso de envío de evento) y ejecutará el método done
en el subproceso de envío de evento.
Entonces, al usar SwingWorker, no tiene que preocuparse por el funcionamiento interno de los eventos de IU en el EDT y las tareas lentas en otro hilo.
Sí, puedes utilizar un SwingWorker
la idea es que una tarea que lleva mucho tiempo ejecutar en un hilo separado (hilo de fondo), entonces no bloqueas tu GUI y tu JFrame no se congelará. Aquí hay un ejemplo completo que realmente me gusta Swing Worker Example .
Básicamente, como ejemplo, creas tu propia clase que extiende SwingWorker
anula doInBackground
.
NOTA: puede tener campos como una clase normal.
Ejemplo:
class Worker extends SwingWorker<Void, String> {
private SomeClass businessDelegate;
private JLabel label;
@Override
protected Void doInBackground() throws Exception {
//here you make heavy task this is running in another thread not in EDT
businessDelegate.callSomeService();
setProgress(30); // this is if you want to use with a progressBar
businessDelegate.saveToSomeDataBase();
publish("Processes where saved");
return null;
}
@Override
protected void process(List<String> chunks){
//this is executed in EDT you can update a label for example
label.setText(chunks.toString());
}
//add setters for label and businessDelegate
}
También leyó sobre el process(..)
publish(..)
y done()
.
Y en tu código de cliente acaba de poner.
SwingWorker<Void,String> myWorker = new Worker();
myWorker.execute();