Я создал программу, которая ищет файлы в исходной папке. Если он находит какой-либо файл, он обрабатывает этот файл и перемещает его в папку назначения, а затем ищет новый файл в исходной папке. Он должен постоянно проверять исходную папку для файла.
Я использовал поток для поиска файлов в исходной папке. Проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда во время обработки файла возникает какое-либо исключение, поток останавливается. Я хочу, чтобы поток работал даже в случае возникновения исключения. Он должен переместить файл, вызвавший ошибку, в другую папку и найти новый файл в исходной папке. Как я могу заставить поток продолжать работать?
Например:
public void run() {
try {
searchfile();
}
catch(Exception e) {
e.printStackTrace();
}
}
public void searchfile(){
...
}
Обновлять:
Я должен быть более ясным в своем вопросе. Фактически существует 4 исходные папки и 4 целевые папки. Я должен выполнить одну и ту же операцию в каждой паре источника и назначения. Итак, я создал 4 потока в одном классе и выполняю операцию в отдельном классе.
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(){ ... } }
Весь поток не перестанет работать, даже если он поймал какое-либо исключение в середине. Как я могу это сделать?




Если поток умирает из-за неперехваченного исключения, ответ прост: перехватите исключение в подходящем месте, чтобы продолжить работу. Либо перехватите исключение в своем методе searchfile, либо заставьте метод run вызывать searchfile в цикле.
Внутри вашего улова вы можете переместить файл в папку ошибок, затем создать новый объект того же потока и запустить его снова.
если я не понял вас неправильно, в вашем коде отсутствует характер "продолжать работу", т.е. вам нужно где-то создать цикл:
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
}
}
обратите внимание, что это просто очень простое расширение вашего примера. по-прежнему отсутствует параметризация SearchTask, чтобы быть конкретной для папки, обработки файлов и исключений и т.д., как упоминалось в предыдущих ответах, ваша SearchTask должна реализовывать Runnable (я предпочитаю Callable ...), и IMHO это всегда лучше использовать ExecutorService, а не создавать потоки вручную. надеюсь это поможет...
вы сказали, что во время файлового процесса может возникнуть исключение, поэтому я помещаю processFile() в блок try-catch. но если он может быть брошен во время поиска, вы также можете поместить его в пробную ловушку.
public void run() {
while(!terminated) {
findNextFile();
try {
processFile();
} catch {
// handle error
}
}
}
Если вы хотите, чтобы ваш поток продолжал работать, используйте цикл.
public void run() {
while(!Thread.interrupted())
try {
searchfile();
}
catch(Exception e) {
e.printStackTrace();
}
}
Вот мои предположения, основанные на вашем вопросе и ваших пояснениях:
run() вызывает searchfile() только один раз, а не в цикле.searchfile() есть цикл, и вы хотите, чтобы этот цикл продолжал работать, даже если в нем возникло исключение.searchfile() не заявляет, что выкидывает какие-либо ExceptionSystem.out (хотя использование среды ведения журнала - действительно хорошая идея.for() нижеИсходя из этих предположений, вы не хотите планировать обнаружение Exception в вашем методе run(), кроме как с целью регистрации того, что что-то пошло не так:
public void run() {
try {
searchfile();
} catch (RuntimeException e) {
System.out.println("Something went very wrong! Unexpected RuntimeException");
e.printStackTrace();
}
}
Обратите внимание, что код перехватывает RuntimeException. Всегда выбирайте наиболее подходящий Exception, который сделает то, что вам нужно. Тогда вам понадобится что-то вроде следующего в вашем методе 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
}
}
Поскольку вы захватываете неожиданные Exception в основном цикле вашего Thread, ваш поток продолжит обработку после обработки Exception.
Я не совсем уверен, что это сработает, но попробую.
public void run() {
try {
searchFile();
} catch(Exeption e) {
e.printStackTrace();
if (!Thread.currentThread().isAlive())
Thread.currentThread().start();
}
}
Вы можете легко найти обходной путь. Просто запустите необходимую логику несколько раз и завершите работу по некоторым критериям.
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;
}
}
И на выходе
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