What is the Executor framework and why use it over raw th… — Cracked Java
// Concurrency & Multithreading · Executors & Thread Pools
JuniorTheoryEPAM

What is the Executor framework and why use it over raw threads?

The Executor framework is the java.util.concurrent abstraction that separates task submission from task execution, so you hand work to a managed pool of reusable threads instead of spawning a new Thread() per job.

Why not raw threads

A new Thread() per task fails at three things: cost, control, and correctness. Each platform thread reserves around 1 MB of stack and a kernel thread, so unbounded creation under load means context-switch thrashing and eventually OutOfMemoryError: unable to create new native thread. Raw threads also give you no queueing, no result, no lifecycle, and no back-pressure — nothing throttles how many run at once.

A pool fixes all of that: threads are created once and reused, concurrency is bounded, and overflow work waits in a queue (or is rejected) rather than melting the host.

The interface hierarchy

  • Executor — one method, execute(Runnable). The minimal "run this somewhere" contract.
  • ExecutorService — adds lifecycle (shutdown, awaitTermination) and submit, which returns a Future carrying a result or exception, plus invokeAll / invokeAny.
  • ScheduledExecutorService — adds schedule, scheduleAtFixedRate, scheduleWithFixedDelay.
ExecutorService pool = Executors.newFixedThreadPool(8);
try {
    Future<Integer> f = pool.submit(() -> heavyCompute());   // Callable -> Future
    pool.execute(() -> log.info("fire and forget"));         // Runnable
    Integer result = f.get();                                // blocks for the value
} finally {
    pool.shutdown();                                         // stop accepting, drain
    pool.awaitTermination(30, TimeUnit.SECONDS);
}

What you gain

You program against the interface, so the policy — pool size, queue, rejection, even virtual-thread-per-task — becomes a one-line configuration change. You get Future for results and exception propagation, clean shutdown semantics, and a single place to tune throughput. The framework is also the foundation everything else builds on: CompletableFuture, parallel streams, and @Async all run on Executors underneath.

Mark your status