2009-01-22 19 views
7

Utworzyłem program wyszukujący pliki w folderze źródłowym. Jeśli znajdzie dowolny plik, przetwarza ten plik i przenosi go do folderu docelowego, a następnie szuka nowego pliku w folderze źródłowym. Musi on nadal sprawdzać folder źródłowy pliku.Jak zrestartować wątek w java?

Użyłem wątku do wyszukiwania plików w folderze źródłowym. Problem, z którym się borykam, to ilekroć wyjątek jest zgłaszany podczas przetwarzania pliku, wątek zostaje zatrzymany. Chcę, aby wątek działał, nawet jeśli zostanie zgłoszony wyjątek. Musi przenieść plik, który spowodował błąd do innego folderu i poszukać nowego pliku w folderze źródłowym. Jak mogę sprawić, aby wątek dalej działał?

Np

public void run() { 
    try { 
     searchfile(); 
    } 
    catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 

public void searchfile(){ 
    ... 
} 

Aktualizacja:

powinienem być bardziej jasne w moim pytaniu. Właściwie istnieją 4 foldery źródłowe i 4 foldery docelowe. Muszę wykonać tę samą operację w każdej docelowej parze & źródła. Stworzyłem 4 wątki w jednej klasie i wykonałem operację w oddzielnej klasie.

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(){ ... } } 

Wszystkie wątki nie przestaną działać, mimo że przechwycono wyjątek w środku. Jak mogę to zrobić?

Odpowiedz

14

Jeśli wątek umiera z powodu nie przechwyconego wyjątku, odpowiedź jest prosta: złap wyjątek w odpowiednim miejscu, aby można było kontynuować. Złap wyjątek w metodzie pliku wyszukiwania lub uruchom wywołanie metody searchfile w pętli.

1

Wewnątrz haczyka można przenieść plik do folderu błędów, a następnie utworzyć nowy obiekt tego samego wątku i uruchomić go ponownie.

1

chyba mam Ci źle, kod brakuje „Keep działa” naturę, to znaczy trzeba mieć pętlę gdzieś:

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 
    } 

} 

pamiętać, że jest to bardzo proste przedłużenie swoim przykładzie. wciąż brakuje parametryzacji SearchTask, aby była konkretna dla folderu, obsługa wyjątków w plikach &, jak wspomniano w poprzednich odpowiedziach, Twoja funkcja SearchTask powinna implementować Runnable (wolę Callable ...), a IMHO jest zawsze lepiej używać ExecutorService, niż ręcznie spawać wątki. Mam nadzieję, że to pomoże ...

0

Powiedziałeś, że wyjątek może zostać zgłoszony podczas procesu tworzenia pliku, więc wstawiam processFile() w blok try-catch. ale jeśli może zostać rzucony podczas wyszukiwania, możesz również umieścić go w try-catch.

public void run() { 
    while(!terminated) {  
     findNextFile(); 
     try { 
      processFile(); 
     } catch { 
      // handle error 
     } 
    } 
} 
2

Jeśli chcesz, aby wątek działał dalej, użyj pętli.

public void run() { 
    while(!Thread.interrupted()) 
     try { 
      searchfile(); 
     } 
     catch(Exception e) { 
      e.printStackTrace(); 
     } 
} 
+0

oops zbyt powolny, ale 11 godzin! –

0

Oto moje założenia oparte na pytanie i wyjaśnienia:

  • Każdy wątek w sposobie run(), tylko nazywa searchfile() raz i nie w pętli
  • metoda searchfile() ma zapętli się i chcesz, aby pętla kontynuowała działanie, nawet jeśli zostanie w nim zgłoszony wyjątek.
  • masz jakiś sposób inicjowania każdego wątku, że nie pokazano nam (i to nie jest strasznie ważne dla tej konkretnej quiestion)
  • searchfile() nie oświadczyć, że wyrzuca dowolny Exception
  • Nie jesteś za pomocą ramy rejestrowania, ale zamiast tego są przy użyciu System.out (choć za pomocą ramy rejestrowania jest naprawdę dobry pomysł
  • Java 5 jest OK (w przeciwnym razie będziesz musiał użyć innego for() pętli poniżej

z tymi assumpti ons, nie chcesz, aby zaplanować złapać Exception w swojej metodzie run() wyjątkiem celów rejestrowania, że ​​coś poszło bardzo źle:

public void run() { 
    try { 
     searchfile(); 
    } catch (RuntimeException e) { 
     System.out.println("Something went very wrong! Unexpected RuntimeException"); 
     e.printStackTrace(); 
    } 
} 

Należy pamiętać, że kod łapie RuntimeException. Zawsze łapaj najbardziej konkretny Exception, który zrobi to, czego potrzebujesz. Następnie co potrzebne jest coś takiego jak w następujący sposób 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 
    } 
} 

Ponieważ jesteś zatrzymując nieoczekiwane Exception S w pętli głównej swojej Thread, Twój wątek będzie kontynuować przetwarzanie po stosowaniu Exception.

1

Nie jestem do końca pewien, czy to zadziała, ale oto jest próba.

public void run() { 
    try { 
     searchFile(); 
    } catch(Exeption e) { 
     e.printStackTrace(); 
     if(!Thread.currentThread().isAlive()) 
      Thread.currentThread().start(); 
    } 
} 
0

Możesz łatwo przejść z obejściem. Po prostu uruchom wymaganą logikę kilka razy i zakończ zadanie na podstawie pewnych kryteriów.

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; 
} 
} 

a wyjście jest

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