code: public void read(final long address, final byte[] data) throws Exception {
  
          if (blockCount == -1) {
              throw new IllegalStateException("You first have to open the Device!");
          }
  
          if (data.length % extendSize != 0) {
              throw new IllegalArgumentException("Number of bytes is not a multiple of the extend size ("
                  + extendSize + ")!");
          }
  
          int fragments = data.length / extendSize;
          int blocks = data.length / blockSize;
          int blockFactor = extendSize / blockSize;
  
          if (address < 0 || address + blocks > blockCount) {
              long adr = address < 0 ? address : address + blocks - 1;
              throw new IllegalArgumentException("Address " + adr + " out of range.");
          }
  
          int parts = (fragments >= devices.length) ? devices.length : fragments;
          barrier = new CyclicBarrier(parts + 1);
          long actualAddress = ((address / blockFactor) / devices.length) * blockFactor;
          int actualDevice = (int)((address / blockFactor) % devices.length);
          List<byte[]> deviceData = new Vector<byte[]>();
          int deviceBlockCount;
          for (int i = 0; i < parts; i++) {
              deviceBlockCount = fragments / devices.length * blockFactor;
              if (i < (fragments % devices.length)) {
                  deviceBlockCount += blockFactor;
              }
              deviceData.add(new byte[deviceBlockCount * blockSize]);
  
              if (deviceBlockCount != 0) {
                  executor.execute(new ReadThread(devices[actualDevice], actualAddress, deviceData.get(i)));
              }
              if (actualDevice == devices.length - 1) {
                  actualDevice = 0;
                  actualAddress += blockFactor;
              } else {
                  actualDevice++;
              }
          }
          barrier.await();
  
          /** Merge the results. */
          for (int i = 0; i < fragments; i++) {
              System.arraycopy(deviceData.get(i % devices.length), i / devices.length * extendSize, data, i
                  * extendSize, extendSize);
          }
      }
docs: {@inheritDoc}