问题
I am using a ScheduledExecutorService
to execute a task that calls a service at a fixed rate. The service may return some data to the task. The task stores data in a queue. Some other threads slowly pick items from the queue
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class EverlastingThread implements Runnable {
private ScheduledExecutorService executorService;
private int time;
private TimeUnit timeUnit;
private BlockingQueue<String> queue = new LinkedBlockingQueue<String>(500);
public EverlastingThread(ScheduledExecutorService executorService, int time, TimeUnit timeUnit) {
this.executorService = executorService;
this.time = time;
this.timeUnit = timeUnit;
}
public void run() {
// call the service. if Service returns any data put it an the queue
queue.add("task");
}
public void callService() throws Exception {
// while queue has stuff dont exucute???????????
executorService.scheduleAtFixedRate(this, 0, time, timeUnit);
}
}
How do I pause the executorService until the queue populated by the task has been cleared.
回答1:
When an executor is shudown, it do no longer accept new task and wait for the current ones to terminate. But you don't want to terminate your executor, just pause it.
So what you can do, is that in your task you just deal with an empty queue. Because you task is only to be executed from time to time, CPU consumption will be near to 0 for it when there is no processing to do. this is the "if(!queue.isEmpty()) return;" from Peter Lawrey response.
Second, you use a blocking queue. That mean that if you call the method take() to get a queued element while the queue is empty, the executor thread will wait until some element is added to the queue automatically.
So:
- You can't pause an executor an even it would complicate your code.
- A blocking queue do by design exactly what you need: blocking the task if the queue is empty.
- if you prefer you can just let the periodic task run and check if the queue isEmpty.
- You should already use one or the other way in your task anyway otherwise you would have NullPointerException when the queue is empty.
回答2:
You can do
if(!queue.isEmpty()) return;
at the start.
If you are usin a ScheduledExecutorService which has a queue, why are you using it to add to another queue. Can you not just use the queue in the service?
来源:https://stackoverflow.com/questions/6545204/pause-scheduledexecutorservice