如何在java中重启线程?

时间:2009-01-22 07:04:26

标签: java multithreading exception

我创建了一个搜索源文件夹中文件的程序。如果找到任何文件,它会处理该文件并将其移动到目标文件夹,然后在源文件夹中查找新文件。它必须继续检查文件的源文件夹。

我使用线程在源文件夹中查找文件。我面临的问题是,在文件处理期间抛出任何异常时,线程都会停止。即使抛出异常,我也希望线程能够运行。它必须将导致错误的文件移动到其他文件夹并在源文件夹中查找新文件。如何让线程继续运行?

例如:

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

所有线程都不会停止运行,尽管它在中间发现任何异常。我怎么能这样做?

8 个答案:

答案 0 :(得分:14)

如果一个线程因未捕获的异常而死亡,答案很简单:在适当的地方捕获异常,以便继续。在searchfile方法中捕获异常,或者使run方法在循环中调用searchfile。

答案 1 :(得分:2)

如果您希望线程继续运行,请使用循环。

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

答案 2 :(得分:1)

在catch中,您可以将文件移动到error文件夹,然后创建同一个线程的新对象并重新启动它。

答案 3 :(得分:1)

除非我弄错了,否则你的代码会缺少“保持运行”的性质,即你需要在某个地方设置循环:

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 ...),而且恕我直言,使用ExecutorService总是比手动生成线程更好。希望这会有所帮助...

答案 4 :(得分:1)

我不完全确定这是否有效,但这是一次尝试。

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

答案 5 :(得分:0)

你说在文件处理过程中可能抛出异常,所以我把processFile()放在try-catch块中。但是如果在搜索过程中可能会抛出它,你也可以把它放在试一试。

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

答案 6 :(得分:0)

以下是基于您的问题和澄清的假设:

  • run()方法中的每个帖子只调用searchfile()一次而不是循环
  • 您的searchfile()方法中有一个循环,您希望该循环继续运行,即使其中引发了异常。
  • 你有一些方法来初始化你没有向我们展示的每个线程(这对于这个特定的静止并不是非常重要)
  • searchfile()未声明它会抛出任何Exception
  • 您没有使用日志框架,而是使用System.out(尽管使用日志框架是一个非常好的主意
  • Java 5没问题(否则你将不得不在下面使用不同的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后继续处理。

答案 7 :(得分:0)

您可以轻松地使用解决方法。只需运行所需的逻辑一段时间,然后根据某些标准完成工作。

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