public void download(
            final @NotNull Factory<? extends InputConnector> inputConnectorFactory,
            final @NotNull Factory<? extends OutputConnector> outputConnectorFactory,
            final @NotNull Iterator<? extends Chunk> chunkIterator,
            final int streamsCount
    ) throws Exception {
        LOGGER.info("Downloading has been started");

        Semaphore semaphore = new Semaphore(0);
        AtomicReference<Exception> exceptionReference = new AtomicReference<>(null);

        for (int streamsCounter = 0; streamsCounter < streamsCount; streamsCounter++) {
            executorService.submit((Runnable) () -> {
                try {
                    try (InputConnector inputConnector = inputConnectorFactory.create()) {
                        LOGGER.info("{} has been successfully created", inputConnector);

                        try (OutputConnector outputConnector = outputConnectorFactory.create()) {
                            LOGGER.info("{} has been successfully created", outputConnector);

                            downloadInternal(inputConnector, outputConnector, chunkIterator);

                            semaphore.release();
                        } catch (Factory.CreationException e) {
                            LOGGER.error("Creation of outputConnector has been failed", e);

                            throw e.getCause();
                        }
                    } catch (Factory.CreationException e) {
                        LOGGER.error("Creation of inputConnector has been failed", e);

                        throw e.getCause();
                    }
                } catch (Exception e){
                    if (exceptionReference.compareAndSet(null, e)) {
                        semaphore.release(streamsCount);
                    }
                }
            });
        }

        semaphore.acquire(streamsCount);
        Exception exception = exceptionReference.get();
        if (exception == null) {
            LOGGER.info("Downloading has been finished");
        } else {
            LOGGER.error("Downloading has been failed in cause of {}", exception);

            throw exception;
        }
    }