Sembra che tu voglia una coda con priorità thread-safe. La priorità sarà basata sul momento in cui ogni URL deve essere recuperato. Quando hai un'attività per recuperare un URL, lo metti in coda. Avrai un pool di thread per gestire le attività in coda. Probabilmente vorrai regolare il numero esatto su alcune statistiche a proposito di 1) per quanto tempo ogni URL impiega a recuperare in media, e 2) quanti URL devi recuperare in un dato momento.
Ad esempio, se mediamente 3 secondi per recuperare i dati per un URL e un URL per recuperare ogni secondo, ovviamente hai bisogno di almeno tre thread per arrivare ragionevolmente vicino al tuo mantenimento. Meno ovviamente, probabilmente vorrai calcolare la varianza (o deviazione standard) del traffico, per avere un'idea di quanti thread hai bisogno per gestire i burst. In alternativa, puoi regolare il numero in modo dinamico, in base alla domanda nei prossimi secondi.
Probabilmente vorrai includere un intervallo di ripetizione nella definizione di un'attività, insieme al numero di (consecutivi?) volte in cui l'attività è fallita. Dopo N ripetizioni, semplicemente non rimetterai l'attività nella coda di esecuzione (o, in alternativa, potresti pianificarne l'esecuzione a intervalli più lunghi, e probabilmente solo quando il sistema è inattivo altrimenti).
Inutile, mi sembra che tu probabilmente stimi il numero di thread coinvolti a meno che la maggior parte di quegli URL finisca molto più vicino ai 2 minuti intervallo rispetto all'intervallo di 1 ora. Se assumiamo una distribuzione approssimativamente casuale, otteniamo qualcosa come un URL per recuperare ogni ~ 1,8 secondi. A quel ritmo, una discussione potrebbe facilmente essere adeguata.