如何使用超时机制中断正在进行的任务?

时间:2012-04-20 09:20:22

标签: java multithreading ftp download

我目前正在开发基于包commons.net的ftp客户端,以便运行测试以查看连接的速度。 基本上我的ftp测试包括连接到服务器,登录到它,然后根据需要开始下载/上传循环,直到用户决定通过按钮停止它,然后当前循环将结束,所以测试

然而,在运行这些测试时,出现了一种需要机制的情况。服务器正在传输文件,并在确实完成之前发送返回代码226(传输完成)。

所以我的线程仍然卡住,试图在不再可能的情况下清空inputStream。

我的想法是在下载过程中启动一个线程计时器,每次将一个字节传输到我的客户端时都会重置。 当超时发生时,会引发异常,并且我的客户端会对此作出反应,并进行下载。

我已阅读并尝试了许多解决方案,其中包括: - 从线程中引发异常 - >线程捕获异常而不是客户端; - 从线程中断客户端,因此客户端引发一个interruptException - >似乎不起作用; - 使用具有超时的执行程序 - >因为我无法知道下载的“正常”持续时间,所以当我开始执行任务时,我无法将其提供给执行程序,而且,当我接收数据时,必须重置计时器。

我在许多论坛上阅读了很多关于它的内容,并没有找到任何似乎适应的解决方案并且在这种情况下工作。如果有人知道另一种方法吗?

这是我正在执行的操作的代码:

public double get(String fileName) {
    [...]
    org.apache.commons.net.io.Util.copyStream(stO,stD,client.getBufferSize(),
                this.localSize,
                new org.apache.commons.net.io.CopyStreamAdapter() {
                    public void bytesTransferred(long totalBytesTransferred,
                            int bytesTransferred,long streamSize) {
                        setProgressDL(totalBytesTransferred);
                        //reset the timer here
                    }
        });
[...]
}

以下是我测试的一些代码,启动了我的客户端:

public class TestFtp extends Thread {
[...]
public void run() {
    System.out.println("Launching FTP test");
    FtpClient client = new FtpClient(this.model, this, this.model.getFtpServer());
    try {
                    //Attempting connection on the server
        client.connect();
        try {
            // Attempting login
            client.login(this.model.getUsername(), this.model.getPassword());
            do {
                client.changeDirectory("get");
                                    // start timer
                client.get(this.model.getDistantFileName());
                                    // stop timer

                client.changeToParentDirectory();
                client.changeDirectory("put");
                client.set(this.model.getDistantFileName(),
                        this.model.getNewFileName());

                client.changeToParentDirectory();
                try {
                    // Little pause between each test
                    Thread.sleep(500);
                } catch (InterruptedException e) {}
                // Continue test until the user stops it
            } while (this.continuous);
            // Once the test is over, logout
            client.logout();

            } catch (FTPLoginException e) {
            // If login fails, the test ends
            System.out.println("Unable to login to the server.");
        }
    } catch (FTPConnectException e) {
        // If connection error, the test ends
        System.out.println("Unable to connect to the server.");
    }
}

如果有人可以提供帮助,请提前感谢您,如果您需要有关我的实际代码的更多信息,我可以在此处添加更多信息。

2 个答案:

答案 0 :(得分:0)

嗯,我很抱歉,但我承认我没有读过您的所有代码,但是如果您想要中断正在运行的线程,请做两件事:

  1. 在try / catch块中运行线程代码,如下所示:
  2. 示例:

    public void run() {
        try {
            // code to run
        } catch (InterruptedException ie) {
            // thread interrupted, may want to do some clean up
            // but must return as quickly as possible to avoid halting external code
        }
    }
    
    1. 在需要时从外部调用上述线程的interrupt()方法。
    2. 示例:

      thread.interrupt();
      

      这将告诉VM在你的线程中抛出InterruptedException,无论它在做什么,让你有机会做一些事情。

      我希望这就是你要找的......

      修改

      好的,一个有效的具体例子:

      public class Driver {
      
      private static int count = 0;
      
      public static void main(String[] args) {
      
          Thread t = new Thread(new Runnable() {
              @Override
              public void run() {
                  try {
                      bigTask();
                  } catch (InterruptedException ie) {
                      System.out.println("Interrupted thread! Count is " + count);
                  }
              }
          });
      
          t.start();
      
          try {
              Thread.sleep(1000);
              System.out.println("Trying to interrupt thread");
              t.interrupt();
          } catch (InterruptedException e) {}
      
      }
      
      private static void bigTask() throws InterruptedException {
          List<BigDecimal> bigs = new ArrayList<BigDecimal>();
          for (int i = 0; i < 10000000; i++) {
              bigs.add(BigDecimal.valueOf(i));
              if (Thread.interrupted()) {
                  throw new InterruptedException();
              }
              count = i;
          }
          System.out.println("Ok, added ten million items, count is " + count);
      }
      

      }

答案 1 :(得分:0)

如果你不想抛出不必要的异常,你应该使用一个布尔标志来控制线程的执行(或runnable):

public class TestFtp extends Thread {
[...]
boolean abort;
public void run() {
    [...]
    do{
      [...]
    } while (this.continuous && !abort);
    if (abort){
      // You might want to do something here
    }else{
      // The stuff you normally do
    }
}
}

然后只需从外部将abort标记设置为false即可。 通过这种方式,您可以更好地控制线程终止的方式,因为thread.interrupt();将具有未定义的行为。