【问题标题】:How to restart thread in java? [duplicate]如何在java中重新启动线程? [复制]
【发布时间】:2010-10-02 20:49:24
【问题描述】:

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

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

例如:

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

所有线程都不会停止运行,即使它在中间捕获了任何异常。我该怎么做?

【问题讨论】:

    标签: java multithreading exception


    【解决方案1】:

    如果线程由于未捕获的异常而死亡,答案很简单:在适当的位置捕获异常,这样您就可以继续运行。要么在你的 searchfile 方法中捕获异常,要么让 run 方法在循环中调用 searchfile。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        除非我弄错了,否则您的代码缺少“继续运行”的性质,即您需要在某处有一个循环:

        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】:

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

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

          【讨论】:

            【解决方案5】:

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

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

            【讨论】:

              【解决方案6】:

              以下是我根据您的问题和您的说明做出的假设:

              • run() 方法中的每个线程只调用一次searchfile(),而不是循环调用
              • 您的searchfile() 方法中有一个循环,您希望该循环即使在其中引发异常时也能继续运行。
              • 您有一些方法可以初始化您没有向我们展示的每个线程(这对于这个特定的问题并不是非常重要)
              • searchfile() 没有声明它会抛出任何 Exception
              • 您没有使用日志框架,而是使用System.out(尽管使用日志框架是一个非常好的主意
              • Java 5 没问题(否则你必须在下面使用不同的 for() 循环

              基于这些假设,您不希望在您的 run() 方法中捕获 Exception,除非是为了记录出现严重错误:

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

              由于您在Thread 的主循环中捕获了意外的Exceptions,因此您的线程将在处理Exception 后继续处理。

              【讨论】:

                【解决方案7】:

                我不完全确定这是否可行,但这里是一个尝试。

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

                【讨论】:

                  【解决方案8】:

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

                  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
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2010-12-25
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-10-10
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多