Skip to content

SerialExecutor Pattern

The SerialExecutor Pattern is a concurrency design pattern used to ensure that a series of tasks are executed sequentially, even when submitted to a multi-threaded or asynchronous executor.^[600-developer__big-data__netty__netty-EventLoopGroup.md]

Implementation Details

The pattern is typically implemented by wrapping an existing Executor instance.^[600-developer__big-data__netty__netty-EventLoopGroup.md] Internally, it maintains a queue (such as an ArrayDeque) to hold pending Runnable tasks and a reference to the currently active task.^[600-developer__big-data__netty__netty-EventLoopGroup.md]

Execution Logic

When a new task is submitted via the execute method, it is wrapped and added to the internal queue.^[600-developer__big-data__netty__netty-EventLoopGroup.md] The wrapper ensures that once the current task finishes, it triggers the scheduling of the next task in the queue.^[600-developer__big-data__netty__netty-EventLoopGroup.md] If no task is currently active, the system immediately polls the next task from the queue and passes it to the underlying executor to begin execution.^[600-developer__big-data__netty__netty-EventLoopGroup.md]

This mechanism creates a "serial" effect, ensuring tasks are processed one after another, effectively decoupling the execution order from the potentially parallel nature of the backing executor.^[600-developer__big-data__netty__netty-EventLoopGroup.md]

Code Example

class SerialExecutor implements Executor {
  final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
  final Executor executor;
  Runnable active;

  SerialExecutor(Executor executor) {
    this.executor = executor;
  }

  public synchronized void execute(final Runnable r) {
    tasks.offer(new Runnable() {
      public void run() {
        try {
          r.run();
        } finally {
          scheduleNext();
        }
      }
    });
    if (active == null) {
      scheduleNext();
    }
  }

  protected synchronized void scheduleNext() {
    if ((active = tasks.poll()) != null) {
      executor.execute(active);
    }
  }
}
  • [[Thread Pool]]
  • [[Concurrency]]
  • [[Executor]]

Sources

^[600-developer__big-data__netty__netty-EventLoopGroup.md]