Если вы хотите допустить наследование от ThreadPoolExecutor, вы можете определить нового Executor, который задерживается после завершения каждого выполнения, следующим образом (с одним потоком в пуле это ограничивает максимальную скорость выполнения задач каждые 1700 мс) :
final ThreadPoolExecutor msgQueue = new ThreadPoolExecutor(1, 1,0L,TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()) {
protected void afterExecute(Runnable r, Throwable t) {
try {
Thread.sleep(Controller.msgWait));
} catch (InterruptedException e) {
log.error("Wait to send message interrupted", e);
}
}
};
, а затем используйте его как обычно:
Future task = msgQueue.submit(new Runnable() {
public void run() {
sendRawLine("PRIVMSG " + msg.channel + " :" + msg.message);
}
});
try {
task.get();
} catch (ExecutionException e) {
log.error("Couldn't schedule send message to be executed", e);
} catch (InterruptedException e) {
log.error("Wait to send message interupted", e);
}
Не обязательно, чтобы он был чище, чем использование ScheduledExecutorService, хотя он избегает синхронизированного блока, объявляя о будущем вне блока и вводя поле Date.