我正在用Java编写一个简单的网络幸存工具。它基本上只需ping一个可变地址范围并将答案保存在数据库中。
首先,我使用了java.net库,但由于它只使用了echo命令,因此网络中的打印机,路由器和某些服务器无法应答。所以我使用了icmp4j库。
由于ping地址范围大约需要10到15分钟,因此在逐个执行此操作时,我决定使用线程将扫描时间降至最低。但问题是,它一次只能ping一个地址。
我之前从未使用过线程,所以这里是代码,以防我犯了一个大错:
//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());
}
这是我的Ping课程:
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-时,线程同时被处理。我已经读过,线程不应该访问相同的资源,所以我想,这就是这里发生的事情。但是我太缺乏分析甚至重写图书馆的经验。
这是我的Ping类,没有使用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 :(得分:1)
回答你为什么代码ping 1只能解决的问题..
while(ar.next()){
try{
//here, I create and start the threads
new Thread(new Ping(ar.getAddress())).start();
我怀疑你的ar.getAddress()
总是返回相同的地址,因此你只是创建了一堆ping同一地址的线程。
并非线程无法访问共享资源。您需要确保资源是线程安全的。
您要做的是为每个ping创建一个线程。这可能是一种不好的做法,尤其是当您拥有大量地址时,因为1)线程创建可能导致开销,2)拥有太多线程会增加资源争用。更好的方法是使用ExecutorService。它为您管理一个线程池,您所要做的就是提交任务(这是一个ping地址)
答案 1 :(得分:1)
创建大量线程可能会使性能变差。最佳线程数取决于许多因素,包括操作系统允许JVM使用的CPU /核心数,以及线程正在执行的工作主要是CPU绑定还是I / O绑定。甚至很难猜出要使用多少线程,但可以肯定地说254太多了。
不是明确创建线程,而是将Runnable
个任务提供给ThreadPoolExecutor
。这样可以轻松地使用线程数。您甚至可能会发现您的操作系统网络堆栈是瓶颈,并且使用多个线程完全没有任何收获。
答案 2 :(得分:0)
在icmp4j库中,我注意到在执行ping请求时,只有基于操作系统的本机桥的分配在Icmp4jUtil类的初始化期间成为线程安全的,并且实际的ping进程执行不是线程安全的。所以,毫无疑问,线程不能同时ping多个地址。它可以ping多个地址。