Я пытаюсь создать очередь задач, которая запускается только один раз каждые throttle
миллисекунды, пока в очереди есть задачи. Кроме того, поскольку задачи создают онлайн-запросы, мне нужно запускать их в другом потоке, чтобы не замедлить работу остальной части приложения. Данные, которые я получаю, не являются «высокоприоритетными», и мне не нужно быстро проходить через очередь, поскольку я хочу, чтобы скорость запроса была минимальной. Я попробовал следующий код, хотя был почти уверен, что он не сработает:
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<>();
this.executor.schedule(
this,
p.getConfig().getInt("requestThrottle", 250), //the int is used as default
TimeUnit.MILLISECONDS);
}
public void addJob(QueryRequest req) {
this.jobs.add(req);
this.notify();
}
@Override
public void run() {
QueryRequest req = this.jobs.poll();
if (req == null) {
try {
this.wait();
} catch (Exception e) { e.printStackTrace(); }
}
else {
req.run();
}
}
}
Как и ожидалось, это приводит к IllegalMonitorStateException
. Я не разбираюсь в многопоточности и понятия не имею, как еще попытаться здесь достичь своей цели. (Потребитель указан в кавычках в названии, потому что он действует как потребитель, но я не уверен, является ли он технически потребителем.) чтобы сделать его работоспособным, но это не соответствует моим предпочтениям по производительности при паузе, когда в очереди нет элемента.
//...snip...
public void addJob(QueryRequest req) {
this.jobs.add(req);
}
@Override
public void run() {
QueryRequest req = this.jobs.poll();
if (req != null) {
req.run();
}
}
}