Rhythmic task controller The purpose of a rhythmic task controller is to accept a task and execute all the queued tasks in a cycle or "rhythm" defined by the client code. A task returns true or false depending on whether or not it is "finished". A finished task should be removed from the controller's control and won't be executed again while an unfinished task should be executed on the next cycle.

I don't think my solution is as well optimized as it could be, and this is a solution that needs to be as fast as possible as it serves as the core task controller in my game framework!

import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public final class RhythmicTaskController implements TaskController, Runnable {

    private final ExecutorService service;
    private final ConcurrentLinkedQueue&lt;Task&gt; queue = new ConcurrentLinkedQueue&lt;&gt;();

    public RhythmicTaskController(int threads, int delay, TimeUnit unit) {
        service = Executors.newFixedThreadPool(threads);

        newSingleThreadScheduledExecutor().scheduleWithFixedDelay(this, delay, delay, unit);
    }

    @Override
    public void offer(Task task) {
        queue.offer(task);
    }

    @Override
    public void run() {
        int initial = queue.size();
        ConcurrentMap&lt;Future&lt;Boolean&gt;, Task&gt; futures = new ConcurrentHashMap&lt;&gt;(initial);
        queue.forEach(task -&gt; futures.put(service.submit(task::finish), task));
        futures.forEach((r, task) -&gt; {
            try {
                if (r.get())
                    queue.remove(task);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

}
You could remove all elements from the queue and then offer them back if necessary.

public void run() {
    ArrayList&lt;Task&gt; tasks = new ArrayList&lt;&gt;();
    {
      Task task;
      while((task = queue.poll()) != null) {
        tasks.add(task);
      }
    }
    for(Task task: tasks) {
      service.submit(() -&gt; {
        if(!task.finish()) offer(task);
      });
    }
}