code: public Writable[] call(Writable[] params, InetSocketAddress[] addresses, 
                           Class<?> protocol, UserGroupInformation ticket)
      throws IOException {
      if (addresses.length == 0) return new Writable[0];
  
      ParallelResults results = new ParallelResults(params.length);
      synchronized (results) {
        for (int i = 0; i < params.length; i++) {
          ParallelCall call = new ParallelCall(params[i], results, i);
          try {
            Connection connection = 
              getConnection(addresses[i], protocol, ticket, 0, call);
            connection.sendParam(call, false);             // send each parameter
          } catch (RejectedExecutionException e) {
            throw new IOException("connection has been closed", e);
          } catch (IOException e) {
            // log errors
            LOG.info("Calling "+addresses[i]+" caught: " + 
                     e.getMessage(),e);
            results.size--;                         //  wait for one fewer result
          } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            LOG.warn("interrupted waiting to send params to server", e);
            throw new IOException(e);
          }
        }
        while (results.count != results.size) {
          try {
            results.wait();                    // wait for all results
          } catch (InterruptedException e) {}
        }
  
        return results.values;
      }
    }
docs: Makes a set of calls in parallel.  Each parameter is sent to the
  corresponding address.  When all values are available, or have timed out
  or errored, the collected results are returned in an array.  The array
  contains nulls for calls that timed out or errored.