public synchronized void stop() throws InterruptedException {
        try {
            saveUnprocessedUrls(executorService.shutdownNow());
            if (executorService.awaitTermination(1_000, TimeUnit.MILLISECONDS)) {
                saveUnprocessedUrls(getCancelledTasksFromExecutor());
            }
        } finally {
            executorService = null;
        }
    }

    private List<Runnable> getCancelledTasksFromExecutor() {
        return Collections.EMPTY_LIST;
    }
private void saveUnprocessedUrls(List<Runnable> unprocessed) {
        for (Runnable task : unprocessed) {
            urlsForProcessing.add(((UrlTask) task).getPage());
        }
    }
1. In stop() method we use saveUnprocessedUrls() method with argument executorService.shutdownNow(). Method shutdownNow() "Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution." saveUnprocessedUrls() adding all not executed task to our original Set with URLs. 2. Next lines are:
if (executorService.awaitTermination(1_000, TimeUnit.MILLISECONDS)) {
                saveUnprocessedUrls(getCancelledTasksFromExecutor());
            }
Waiting for what? Isn't line before all not executed task weren't added to set with URL? I suppose it's something like that: After line 3 in line 4 if some thread from this executor service doing some work, this tasks are saveUnprocessedUrls(getCancelledTasksFromExecutor()); and "canceled" and change in Collections.EMPTY_LIST;? I'm little confuse, and don't get this fragments from that class.