code: @Override
      public V get(final long timeout, final TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
          synchronized (lock) {
              if (value != null) {
                  return value;
              }
              lock.wait(timeUnit.toMillis(timeout));
  
              if (value != null) {
                  return value;
              }
  
              if (throwable != null) {
                  throw new ExecutionException(throwable);
              }
              throw new TimeoutException();
          }
      }
docs: Method blocks until the future is done. The method return the result if the future was normally completed.
  If the future was exceptionally completed or canceled an exception is thrown.
  
  @param timeout  the maximal time to wait for completion.
  @param timeUnit the unit of the given timeout.
  
  @return the result of the task.
  
  @throws InterruptedException is thrown if the thread was externally interrupted.
  @throws ExecutionException   is thrown if the task was canceled or exceptionally completed.
  @throws TimeoutException     in thrown if the timeout was reached and the task is still not done.