2012-04-20 19 views
0

我目前正在開發一個基於commons.net包的ftp客戶端,以便運行測試來查看連接的速度。 基本上我的FTP測試包括在連接到服務器,登錄到它,然後開始下載的週期/根據需要上傳長,直到用戶決定通過一個按鈕來阻止它,那麼當前的週期將結束,因此將考試。如何用超時機制中斷正在進行的任務?

但是,在運行這些測試時,出現了需要定時機制的情況。服務器正在傳輸文件,並在確實完成之前發送返回碼226(傳輸完成)。

所以我的線程仍然卡住,試圖清空inputStream,當它不可能了。

我的想法是先從下載過程的螺紋計時器,這將在每次傳輸一個字節到我的客戶進行復位。 發生超時時,會產生一個異常,我的客戶會對它做出反應,並記錄下載。

我已經閱讀並嘗試了很多解決方案,其中包括: - 從線程引發異常 - >線程捕獲異常而不是客戶端; - 從線程中斷客戶端,所以客戶端引發一箇中斷異常 - >似乎不工作; - 使用具有超時執行器 - >因爲我無法知道下載的「正常」持續時間,所以當我啓動任務時,我無法將其交給執行器,而且,當我接收數據。

我看了很多論壇上很多關於它,並沒有發現,似乎能夠適應任何的解決方案和工作在這種情況下。如果有人有另一種方法來做到這一點的想法?

這是我的表演動作的代碼:

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."); 
    } 
} 

謝謝您提前如果任何人都可以幫助,如果您需要關於我的實際代碼的更多信息,我可以在這裏放更多信息。

+0

猜猜你沒有直接使用InputStream API,否則你可以做類似in.available()的事情?然後讀取,否則等待一段時間,如果仍然沒有數據可用,假設連接丟失。 – 2012-04-20 09:50:32

+0

Thread.interrupt()應該中斷你的線程,並且應該向上拋出異常,除非坐在中間的一些貪婪代碼正在吃它。 – 2012-04-20 09:51:30

回答

0

嗯,我很抱歉,但我承認我沒有看到所有的代碼,但如果你想中斷正在運行的線程,做兩件事情:

  1. 運行試試裏面的線程代碼/ catch塊這樣的:

實施例:

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. 調用線程的中斷()方法上述外部瓦特當需要出現時。

例子:

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

}

+0

啊,忘記提及了,確保你移除了你在sleep()調用周圍的try/catch塊,因爲有可能這就是當你中斷它時線程將會出現的地方! – Renato 2012-04-20 09:40:30

+0

我不能這樣做,因爲你必須在try和catch之間有一段代碼才能拋出這樣的異常,這就是爲什麼我在它們之間放了一個** sleep *,因爲sleep會引發一個interruptException。 – Jzux 2012-04-20 11:40:34

+0

@Jzux您不必爲此而睡,Thread有檢查中斷標誌的方法。您可以使用這些並自己拋出中斷的異常。 – 2012-04-20 17:56:04

0

如果你不想扔掉不必要的異常,你應該使用控制的執行一個布爾標誌線程(或可運行):

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();將會有一個未定義的行爲。

+0

事實上,我不能像你說的那樣控制我的應用程序的行爲,因爲它被**卡住**執行流的副本,所以它不會測試任何布爾值的值。 – Jzux 2012-04-20 11:38:39

+0

然後使用@Renato提出的解決方案,但要注意,您無法控制將執行的操作。 – 2012-04-20 11:43:52

+0

我編輯了Re​​nato的解決方案,並添加了 'if(false)throw new InterruptedException();' 它應該愚弄編譯器並可能工作 – 2012-04-20 11:59:02

相關問題