Java:Threads赢了';t同时发出砰砰声

Java:Threads赢了';t同时发出砰砰声,java,multithreading,echo,ping,icmp,Java,Multithreading,Echo,Ping,Icmp,我正在用Java编写一个简单的网络安全工具。它基本上只需要ping一个可变地址范围并将答案保存在数据库中 起初,我使用了java.net库,但由于它只使用echo命令,打印机、路由器和网络中的一些服务器将无法响应。所以我用了图书馆 由于ping一个254的地址范围大约需要10到15分钟,所以在逐个执行时,我决定使用线程将扫描时间保持在最低限度。但问题是,它仍然一次只ping一个地址 我以前从未使用过线程,因此下面是代码,以防我犯了一个巨大的错误: //the AddressRange class

我正在用Java编写一个简单的网络安全工具。它基本上只需要ping一个可变地址范围并将答案保存在数据库中

起初,我使用了java.net库,但由于它只使用echo命令,打印机、路由器和网络中的一些服务器将无法响应。所以我用了图书馆

由于ping一个254的地址范围大约需要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());
    }
这是我的平课:

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) {}
}
}
所以我想问,如果我犯了一个错误,或者如果有人有使用上述库的经验,知道如何解决这个问题,或者有一个好的替代方案,那么这项工作完成了

  • 要回答您的问题,为什么代码只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。它为您管理一个线程池,您只需提交任务(即发送到平安地址)


  • 创建大量线程可能会降低性能。线程的最佳数量取决于许多因素,包括操作系统允许JVM使用多少CPU/内核,以及线程所做的工作主要是CPU受限还是I/O受限。甚至很难猜测要使用多少线程,但可以肯定的是254太多了


    不要显式地创建线程,而是将
    Runnable
    任务馈送到线程中。这将使处理线程数变得容易。您甚至可能会发现您的操作系统网络堆栈是瓶颈,使用多个线程根本不会带来任何好处。

    在icmp4j库中,我注意到,在执行ping请求的Icmp4jUtil类初始化期间,只有基于操作系统的本机网桥的分配是线程安全的,而实际的ping进程执行不是线程安全的。因此,毫无疑问,线程不能同时ping多个地址。它可以ping多个地址。

    无关:
    StringBuilder
    就是这样一个核心类,它甚至在
    java.lang
    包中。编写自己的类并将其命名为
    StringBuilder
    ,这会让任何阅读您的代码的人都感到困惑。谢谢,我不知道这一点。我会改正的我刚刚用多线程编写了ping 140 IP的程序&使用icmp4j库对我来说效果很好,但正如您所说的,java的net库产生了意想不到的结果。在不到一秒钟的时间里,我得到了100个ping结果。您是否收到任何错误或异常?通过逐个删除ping步骤彻底调试!!地址不一样,我敢肯定。我要试试这项服务。听起来它可以解决我的问题。我已经用wireshark对它进行了测试,直到现在,它一次只激活一个ping命令。因此,很难判断网络堆栈是否是问题所在。ThreadPoolExecutor听起来是个好主意,我一定会尝试一下。但由于我不太适合编码,所以可能需要一段时间才能弄明白如何使用那些java.util.concurrent库。但如果你想的话,我会随时通知你。