[concurrency-interest] Creating a Set of pings

Tim Peierls tim at peierls.net
Mon May 22 23:19:35 EDT 2006

If you don't mind doing all step 1 work before all step 2/3 work, use
ExecutorService.invokeAll on a collection of Callable<InetAddress> tasks
that test isReachable.

For each of these that succeeds, create a new Callable<InetAddress> that
tries to connect on port 161, and pass a collection these new tasks to
another invocation of ExecutorService.invokeAll.

For each of these that succeeds, put the resulting InetAddress into a plain
HashSet -- CopyOnWriteArrayList is for lists that are frequently read by
different threads but rarely written to. This set need only be accessed by
one thread, the thread that creates it and compares it to some previous
value -- this previous value could be a thread-safe set if other threads
need to access it.

Here's an uncompiled, untested, and possibly completely wrong-headed sketch:

ExecutorService exec = ...;
Collection<InetAddress> addrs = ...;

List<Callable<InetAddress>> testReachableTasks =
    new ArrayList<Callable<InetAddress>>();
for (final InetAddress addr : addrs) {
    testReachableTasks.add(new Callable<InetAddress>() {
        public InetAddress call() {
            return isReachable(addr) ? addr : null;
List<Future<InetAddress>> reachables =

List<Callable<InetAddress>> tryConnectTasks =
    new ArrayList<Callable<InetAddress>>();
for (Future<InetAddress>> reachable : reachables) {
    // need to handle exceptions thrown by Future.get()
    final InetAddress addr = reachable.get();
    if (addr == null) continue;

    tryConnectTasks.add(new Callable<InetAddress>() {
        public InetAddress call() {
            return (canConnectUdp (addr)
                 || canConnectSnmp(addr)) ? addr : null;
List<Future<InetAddress>> connectables =

Set<InetAddress> result = new HashSet<InetAddress>();
for (Future<InetAddress>> connectable : connectables) {
    // need to handle exceptions thrown by Future.get()
    InetAddress addr = connectable.get();
    if (addr != null) result.add(addr);
// compare result to previous result

If you want to start doing step 2/3 work before all step 1 work is complete,
use 2 instances of ExecutorCompletionService, one corresponding to each call
to invokeAll, and pull completed tasks off of one completion queue to insert
it into the next. It's a little trickier, since you have to count
submissions to know when you're done with a completion queue.

I can't advise on how to size the pool. How many network interfaces are
there? How many processors are there? Seems like something you'd want to be
able to tune.


On 5/22/06, robert lazarski <robertlazarski at gmail.com> wrote:
> Could someone please give some advice on these requirements?
> 1) Find all IP's on a given subnet that responds to ICMP  (ping). So for
> say with a netmask of, attempt a ping to 255
> addresses. In java  I believe I can use InetAddress.isReachable(timeout) .
> 2) On a valid IP, try to connect on port 161 via UDP and snmp.
> 3) Put the valid IP's inside an implementation of java.util.Set .
> 4) Compare new Set with a previous Set and show updates.
> My questions are:
> 1) Perform steps 1, 2, and possibly 3 in a Callable or Runnable. On
> typical intel hardware does an ExecutorService with a size of 5 sound about
> right?
> 2) Should I pass in a Callable and get the results back 255 times, or
> should I use Runnable and have the threads write the result to a common
> area, ie, an object with a synchronized method ?
> 3) Should I use one of the concurrent collections to store the results?
> CopyOnWriteArrayList seems to fit.
> Thanks for any help,
> Robert
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at altair.cs.oswego.edu
> http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: /pipermail/attachments/20060522/9e37001c/attachment.html 

More information about the Concurrency-interest mailing list