5

I have a program which sends a ping request to the servers. The list is large and if an IP is unreachable it takes time to go to the next IP.

I wish that, for every IP, it should create a new thread & process all of them simultaneously.

Here is the code:

for (int i = 0; i < 89; i++)
{
     ProcessBuilder processBuilder = new ProcessBuilder("ping", isWindows? "-n" : "-c", "1", buttons[i].getText());
     Process proc = processBuilder.start();
     returnVal = proc.waitFor();                       
}

How can I make this code to ping all IPs, each in a separate thread ?

Onik
  • 19,396
  • 14
  • 68
  • 91
Harshit
  • 5,147
  • 9
  • 46
  • 93
  • See [java code to ping an IP address](http://stackoverflow.com/questions/11506321/java-code-to-ping-an-ip-address). –  May 31 '15 at 08:19
  • Looks like a perfect situation to use CompletableFuture class shipped with Java 8. Check it out! – pnadczuk May 31 '15 at 08:24
  • Those who marked as duplicate, I have not asked to ping and IP address. I want a way to simultaniously start ping of IP address. – Harshit May 31 '15 at 08:28
  • 2
    Just a word of caution. Doing this for a large number of hosts will be **very** slow. A better approach is to do the ping from within java, rather than spawn another process to do the ping. You can read more in this other SO answer http://stackoverflow.com/a/11508356/608820 – Augusto May 31 '15 at 09:09
  • @bogojane you should ping from within java... you could also use async IO to start pinging different ips without waiting for a response from other sockets. – Loïc Faure-Lacroix May 31 '15 at 17:46

2 Answers2

10

How about doing without ProcessBuilder as suggested by others also.

I have three classes - PingParallel is my main class, PingTask is the task performed by each thread, and PingResult is having result code (we can add some more info also, status message etc.).

PingParallel

package com.test.thread;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class PingParallel {

    public static void main(String[] args) {
        int totalIps = 89;
        ExecutorService executor = Executors.newFixedThreadPool(totalIps);
        List<Future<PingResult>> list = new ArrayList<Future<PingResult>>();
        Callable<PingResult> callable = null;
        for(int i=0; i< totalIps; i++){
            callable = new PingTask("127.0.0"+i); // Get the ipAddres buttons[i].getText());
            Future<PingResult> future = executor.submit(callable);
            list.add(future);
        }
        for(Future<PingResult> fut : list){
            try {
                System.out.println(new Date()+ "::"+fut.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        executor.shutdown();
    }
}

PingTask

package com.test.thread;

import java.net.InetAddress;
import java.util.concurrent.Callable;

public class PingTask implements Callable<PingResult> {

  private String ipAddress;

  public PingTask(String ipAddress) {
    this.ipAddress = ipAddress;
  }

  @Override
  public PingResult call() {
    InetAddress inet = null;
    try {
      inet = InetAddress.getByName(ipAddress);
      int resultCode = inet.isReachable(5000) ? 0 : -1;
      return new PingResult(ipAddress, resultCode);
    } catch (Exception e) {
      e.printStackTrace();
      return new PingResult(ipAddress, -1);
    }
  }
}

PingResult

package com.test.thread;

public class PingResult {

  private String ipAddress;
  private int resultCode;

  public PingResult(String ipAddress, int resultCode) {
    this.ipAddress = ipAddress;
    this.resultCode = resultCode;
  }

  public String getIpAddress() {
    return ipAddress;
  }

  public int getResultCode() {
    return resultCode;
  }

  public String toString() {
    return "IpAddress :: "+ ipAddress + " Result Code : "+ resultCode;
  }
}
TheCodingFrog
  • 3,406
  • 3
  • 21
  • 27
2

ProcessBuilder does invoke a new process, but you are effectively killing the parallelism by calling waitFor, since that will wait for the first process to complete before launching the next, making the calls sequential instead. You could either use PB and skip the wait calls, or perhaps use ordinary java threads wrapping calls to Runtime.exec instead.

JHH
  • 8,567
  • 8
  • 47
  • 91
  • If I remove the line `returnVal = proc.waitFor();`, then how can I know if host is reachable or not ? – Harshit May 31 '15 at 08:24
  • Rather than calling the slow, blocking `proc.waitFor` immediately you add `proc` to an `ArrayList`. Once you have all these `proc`s running in parallel have a second loop that goes through the `ArrayList` and calls `proc.waitFor`, most of which will return quickly now, since they are all running in parallel. That said, I agree with everyone who suggests not using Process for this and using native Java instead. – theon May 31 '15 at 10:52