pause - reiniciar un hilo en java
¿Cómo reiniciar el hilo en java? (8)
Dentro de su captura, puede mover el archivo a la carpeta de error, luego crear un nuevo objeto del mismo subproceso y volver a iniciarlo.
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo iniciar / detener / reiniciar un hilo en Java? 10 respuestas
Creé un programa que busca archivos en una carpeta fuente. Si encuentra algún archivo, procesa ese archivo y lo mueve a una carpeta de destino, luego busca un nuevo archivo en la carpeta de origen. Tiene que seguir comprobando la carpeta fuente de un archivo.
He usado un hilo para buscar archivos en la carpeta de origen. El problema al que me enfrento es que cuando se lanza una excepción durante el procesamiento del archivo, el hilo se detiene. Quiero que el hilo se ejecute incluso si se lanza una excepción. Tiene que mover el archivo que causó el error a alguna otra carpeta y buscar un nuevo archivo en la carpeta de origen. ¿Cómo puedo hacer que el hilo siga funcionando?
P.ej:
public void run() {
try {
searchfile();
}
catch(Exception e) {
e.printStackTrace();
}
}
public void searchfile(){
...
}
Actualización :
Debería ser más claro en mi pregunta. En realidad, hay 4 carpetas de origen y 4 carpetas de destino. Tengo que realizar la misma operación en cada par de fuente y destino. Así que he creado 4 hilos en una clase y hago la operación en una clase separada.
class MainClass
{
public static void main(String[] args){
for(int i=0;i<4;i++){
SearchClass search = new SearchClass();
Thread thread = new Thread(search);
thread.start();
}
}
}
class SearchClass
{
public void run() {
try {
searchfile();
} catch(Exception e) {
e.printStackTrace();
}
}
public void searchfile(){ ... } }
Todo el hilo no dejará de funcionar aunque haya atrapado una excepción en el medio. ¿Cómo puedo hacer eso?
Si quieres que tu hilo siga funcionando usa un ciclo.
public void run() {
while(!Thread.interrupted())
try {
searchfile();
}
catch(Exception e) {
e.printStackTrace();
}
}
Si un hilo se está muriendo debido a una excepción no detectada, la respuesta es simple: capture la excepción en un lugar apropiado para que pueda continuar. Capture la excepción dentro de su método searchfile o haga que el método run invoque searchfile en un bucle.
a menos que te haya equivocado, a tu código le falta la naturaleza de "seguir funcionando", es decir, necesitas tener un bucle en alguna parte:
public static void main(String[] args){
ExecutorService service = Executors.newFixedThreadPool(4);
// for each of your 4 folders
while (true) {
Future<File> searchResult = service.submit(new SearchTask());
try {
File foundFile = searchResult.get();
// handle found file
} catch (Exception e) {
// handle exception
}
}
}
private static class SearchTask implements Callable<File> {
@Override
public File call() {
return searchFile();
}
public File searchFile() {
// search & return found file
}
}
tenga en cuenta que esto es solo una extensión muy simple de su ejemplo. todavía falta la parametrización de SearchTask para ser realmente específico para una carpeta, manejo de archivos y excepciones, etc., como se mencionó en respuestas anteriores, su SearchTask debe implementar Runnable (prefiero que se llame ...), y en mi humilde opinión siempre es mejor utilizar un ExecutorService que generar hilos manualmente. espero que esto ayude...
dijiste que la excepción se puede lanzar durante el proceso del archivo, entonces puse el processFile()
en un bloque try-catch. pero si puede arrojarse durante la búsqueda, también puede ponerlo en una trampa de prueba.
public void run() {
while(!terminated) {
findNextFile();
try {
processFile();
} catch {
// handle error
}
}
}
Aquí están mis suposiciones basadas en su pregunta y su aclaración:
- Cada hilo, en el método
run()
, solo llama asearchfile()
una vez y no en un bucle - su método
searchfile()
tiene un bucle y desea que ese bucle continúe ejecutándose incluso si se lanza una excepción. - tienes alguna manera de inicializar cada hilo que no nos estás mostrando (y eso no es terriblemente importante para este reposo específico)
-
searchfile()
no declara que arroja ningunaException
- No está utilizando un marco de trabajo de registro, sino que está utilizando
System.out
(aunque el uso de un marco de registro es una idea realmente buena) - Java 5 está bien (de lo contrario, tendrá que usar un bucle
for()
diferentefor()
continuación
Con estas suposiciones, no desea planear atrapar una Exception
en su método run()
excepto para el registro de que algo salió muy mal:
public void run() {
try {
searchfile();
} catch (RuntimeException e) {
System.out.println("Something went very wrong! Unexpected RuntimeException");
e.printStackTrace();
}
}
Tenga en cuenta que el código captura RuntimeException
. Siempre capture la Exception
más específica que hará lo que necesita. Entonces, lo que necesita es algo como lo siguiente en su método searchfile()
:
File[] files = directory.listFiles();
for (File file : files) {
try {
// Do your normal file/directory processing here
} catch (Exception e) {
System.out.println("Exception processing file " + file.getName() + " " + e);
// Move "file" to another area
}
}
Dado que está atrapando Exception
inesperadas en el bucle principal de su Thread
, su subproceso continuará el procesamiento después de manejar la Exception
.
No estoy del todo seguro de si esto funcionará, pero aquí hay una oportunidad.
public void run() {
try {
searchFile();
} catch(Exeption e) {
e.printStackTrace();
if(!Thread.currentThread().isAlive())
Thread.currentThread().start();
}
}
Puede ir fácilmente con una solución alternativa. Simplemente ejecute la lógica necesaria algunas veces y termine el trabajo según algunos criterios.
public class ThreadRestartWorkaround extends Thread {
public static void main(String[] args) {
ThreadRestartWorkaround th = new ThreadRestartWorkaround(5);
th.start();
}
private int maxCycles;
private int currentCycle;
public ThreadRestartWorkaround(int maxCycles) {
this.maxCycles = maxCycles;
}
@Override
public void run() {
while(executeSomeLogicUntilReachingTheLimit());
System.out.println("Finished due to exceeding the maxCycles config");
}
private boolean executeSomeLogicUntilReachingTheLimit() {
currentCycle++;
System.out.println("Executing logic for " + currentCycle + " time");
return currentCycle < maxCycles;
}
}
Y la salida es
Executing logic for 1 time
Executing logic for 2 time
Executing logic for 3 time
Executing logic for 4 time
Executing logic for 5 time
Finished due to exceeding the maxCycles config