我正在尝试创建一个任务队列,当队列中有任务时,该队列仅每 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
。我没有多线程经验,也不知道如何在这里尝试我的目标。 (消费者在标题中被引用,因为它的行为有点像消费者,但我不确定它在技术上是否是消费者。)
编辑:通过删除 wait()
和 notify()
部分,我能够使其正常工作,但它不符合我在出现问题时暂停的性能偏好队列中没有项目。
//...snip...
public void addJob(QueryRequest req) {
this.jobs.add(req);
}
@Override
public void run() {
QueryRequest req = this.jobs.poll();
if (req != null) {
req.run();
}
}
}
最佳答案
您可能真正需要的是 bulkhead ,但要自己执行此操作,您只需修复 run
方法,使其在没有请求等待时立即返回。按计划重复调用 run
是执行器的工作。
请注意,如果您正在管理自己的执行程序,则应该有一个 shutdown()
方法来彻底关闭它;在容器环境中,该方法应注释为@PreDestroy
。
关于Java throttle "Consumer"线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61620737/