问题
I made the following code with the intention of
- Creating one thread dedicated to performing a possibly slow network request AND
- Ensuring a delay between network requests
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
}
}
}
It has two problems however:
- It only runs a single job even when multiple jobs have been added
- If the throttle setting is set low then it wastes resources checking the queue
The first problem is more important because it isn't doing it's job at all. It should steadily work through the entire queue but as stated it performs the first request and nothing else. The second is potentially a problem later because I'd like to allow it to go lower than 200ms. I'd prefer to have it wait until it gets a new job before continuing whenever it runs out of items in the queue.
来源:https://stackoverflow.com/questions/61626342/java-throttled-consumer-only-runs-once