Я сделал следующий код с целью:
- Создание одного потока, предназначенного для выполнения возможно медленного сетевого запроса И
- Обеспечение задержки между сетевыми запросами
public class QueryManager implements Runnable {
private Plugin p;
private ScheduledExecutorService executor;
private ConcurrentLinkedQueue<QueryRequest> jobs;
public QueryManager(Plugin p) {
this.p = p;
this.executor = Executors.newSingleThreadScheduledExecutor();
this.jobs = new ConcurrentLinkedQueue<>();
int throttle = Math.max(p.getConfig().getInt("requestThrottle", 250), 200);
this.executor.schedule(this, throttle , TimeUnit.MILLISECONDS);
Verbose.debug("Request throttle set to ", Integer.toString(throttle), TimeUnit.MILLISECONDS.name());
}
public void addJob(QueryRequest req) {
this.jobs.add(req);
Verbose.debug("Added query task to queue: ", req.getName());
}
@Override
public void run() {
//I haven't checked if this is running as scheduled...
QueryRequest req = this.jobs.poll();
if (req != null) {
//but have checked and this block is only ever reached once
//I don't know why 'req' wold be null when there are other items in queue
Verbose.debug("Processing job...");
req.run(); //the one job that does run does so correctly
}
}
}
Однако у него есть две проблемы:
- Он запускает только одно задание, даже если было добавлено несколько заданий
- Если настройка дроссельной заслонки установлена на низком уровне, то она тратит ресурсы на проверку очереди
Первая проблема более важна, потому что она совсем не выполняет свою работу. Он должен стабильно работать через всю очередь, но, как указано, выполняет первый запрос и ничего больше. Второй вариант может стать проблемой позже, потому что я хотел бы, чтобы значение go было ниже 200 мс. Я бы предпочел, чтобы он подождал, пока получит новое задание, прежде чем продолжать, когда в очереди заканчиваются элементы.