Loop through List multi-threading to ping hostnames
I think what you are looking for is the Callable&lt;T&gt; interface:


  A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call.


Instead of having to pass around a thread-safe Collection to gather your non-pingable servers, you can call ExecutorService.invokeAll(Collection) to get a List&lt;Future&lt;T&gt;&gt;, which you can then retrieve the results.

First, I'll suggest having an implementation of Callable&lt;T&gt;:

public class Ping implements Callable&lt;String&gt; {

    private final String hostname;

    public Ping(String hostname) {
        this.hostname = hostname;
    }

    public String call() {
        // ... try to ping server
        // assume the results are stored in a boolean
        return isPingable ? "" : hostname;
    }

}


And then you can construct your Collection&lt;Ping&gt; to submit to the ExecutionService:

List&lt;Ping&gt; pingTasks = new ArrayList&lt;Ping&gt;(nonReplicatingRegisters.size());
for (RegisterReplicationSynchTime nonReplicatingRegister : nonReplicatingRegisters) {
    pingTasks.add(new Ping(nonReplicatingRegister.getRegisterName()));
}
// or use invokeAll(Collection, long, TimeUnit) for an explicit timeout
List&lt;Future&lt;String&gt;&gt; taskResults = es.invokeAll(pingTasks);
List&lt;String&gt; results = new ArrayList&lt;String&gt;();
for (Future&lt;String&gt; taskResult : taskResults) {
    try {
        String output = taskResult.get();
        if (!output.isEmpty()) {
            results.add(output);
        }
    } catch (InterruptedException e) {
        // handle accordingly
    } catch (ExecutionException e) {
        // handle accordingly
    }
}