2015-08-28 38 views
2

我正在用Java寫一個簡單的網絡生存工具。它基本上只需要ping變量地址範圍並將答案保存在數據庫中。Java:線程不會同時ping通

起初,我用java.net庫,但由於它只是使用echo命令,打印機,路由器和某些服務器在網絡中不會回答。所以我使用了icmp4j庫。

既然花了大約10到15分鐘逐一做,當它來ping的254,一個地址範圍,我決定使用線程掃描時間保持在最低限度。然而問題在於,它一次只能打一個地址。

我從來沒有使用線程工作過,所以這裏是代碼,以防萬一我犯了一個巨大的錯誤:

//the AddressRange class just saves the current address and counts it up by one 
    AddressRange ar = new AddressRange(tFStart.getText(), tFEnd.getText(), false); 

    //next() checks, if the last address is reached and returns false, if that is the case 
    while(ar.next()){ 
     try{ 
      //here, I create and start the threads 
      new Thread(new Ping(ar.getAddress())).start(); 
     } catch (Exception f) {} 

     //counts up the address by one 
     ar.countUp(ar.getAddressBits()); 
    } 

這裏是我的平安等級:

public class Ping implements Runnable{ 

private final String address; 

public Ping(String address){ 
    this.address = address; 
} 
@Override 
public void run() { 

     IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest(); 
     request.setHost(address); 

    try{    
     IcmpPingResponse response = IcmpPingUtil.executePingRequest(request); 
     String formattedResponse = IcmpPingUtil.formatResponse(response); 
     String output = "Destination: " + address + " \n" + formattedResponse + " \n"; 

     if(formattedResponse.contains("Reply")){ 
      InetAddress addr = InetAddress.getByName(address); 
      output += "Hostname: " + verifyHostName(addr.getHostName()) + " \n"; 
      System.out.println(output); 
      saveClient(new PingData(output)); 
     } 

    } catch (Exception f) {} 
} 
} 

當我用java.net庫替換了icmp4j-,線程同時被處理。我讀過,線程不應該訪問相同的資源,所以我想,這就是發生在這裏的事情。但我還沒有經驗來分析甚至重寫庫。

這裏是沒有icmp4j的使用我的平安等級:

public class Ping implements Runnable{ 

private final String address; 

public Ping(String address){ 
    this.address = address; 
} 
@Override 
public void run() { 

    try{ 
     InetAddress addr = InetAddress.getByName(address); 

     if(addr.isReachable()){ 
      String output += "Hostname: " + verifyHostName(addr.getHostName()) + " \n"; 
      System.out.println(output); 
      saveClient(new PingData(output)); 
     } 
    } catch (Exception f) {} 
} 
} 

所以我想問,如果我犯了一個錯誤,或者如果有人有與所述庫的經驗,知道如何解決這個問題,或者有一個很好的選擇,它完成了工作。

+0

無關:'StringBuilder'就是這樣一個* core *類,它甚至在'java.lang'包中。編寫自己的類並調用它'StringBuilder'將會讓任何讀取你的代碼的人都感到困惑。 – Andreas

+0

謝謝,我不知道。我會糾正它。 :) – Sebowski

+0

我剛剛寫了程序來ping多線程的IP 140和它對icmp4j庫的工作正常,但正如你所說,Java的網絡庫是給予意想不到的結果。在不到一秒鐘的時間裏,我得到了100次ping結果。你是否收到任何錯誤或異常?通過逐個刪除ping步驟徹底調試它! –

回答

1
  1. 要回答你的問題,爲什麼代碼坪只有1個地址..

    while(ar.next()){ 
        try{ 
         //here, I create and start the threads 
         new Thread(new Ping(ar.getAddress())).start(); 
    

    我懷疑你ar.getAddress()總是返回相同的地址,所以你只是創建查驗同一束線程地址。

  2. 這不是線程無法訪問共享資源。您需要確保資源是線程安全的。

  3. 你所要做的是創建一個線程爲每個平。這可能是一個糟糕的做法,特別是當你有很多地址時,因爲1)線程創建可能會導致開銷,2)擁有太多線程會增加資源爭用。更好的方法是使用ExecutorService。它爲你管理一個線程池,你所要做的就是提交任務(即ping一個地址)

+0

地址是不同的,我相信這一點。我將嘗試ExecutorService。聽起來像它可以解決我的問題。 – Sebowski

1

創建大量的線程可能會使性能變差。線程的最佳數量取決於許多因素,包括您的操作系統允許JVM使用多少個CPU /內核,以及線程正在執行的工作主要是CPU限制還是I/O限制。很難猜測有多少線程可以使用,但可以肯定地說254是太多了。

而是明確創建線程,飼料Runnable任務爲ThreadPoolExecutor。這可以讓玩家輕鬆使用多個線程。你甚至可能發現你的OS網絡堆棧是瓶頸,並且使用多線程完全沒有收穫。

+0

我已經用wireshark測試過,直到現在,它一次只激活一個ping命令。所以很難判斷網絡堆棧是否會成爲問題。 ThreadPoolExecutor聽起來像一個好主意,我定義會嘗試一下。但是因爲我不適合編碼,所以在我弄清楚如何使用這些java.util.concurrent庫之前可能需要一段時間。但如果你願意的話,我會保持你的更新。 – Sebowski

0

在icmp4j庫中,我注意到在執行ping請求的同時Icmp4jUtil類的初始化期間,只有基於操作系統的本機橋的分配才成爲線程安全的,並且實際的ping過程執行不是線程安全的。所以,毫無疑問,線程不能同時ping多個地址,它可以ping多個地址。