← Back to Multithreading Course

Class 26: Why We Need the Executor Framework

Part 5 — Managing Threads with the Executor Framework

Welcome to Part 5 of our Java Multithreading course!

So far, we have learned how to create threads, share data safely, coordinate threads, and manage communication between them.

But there is one important question:

Do we really want to create and manage every thread manually in a real-world application?

Imagine an application that receives hundreds or thousands of tasks. Creating a new thread for every task and managing all those threads ourselves can become difficult.

Java provides a better approach called the Executor Framework.

Before learning its interfaces and methods, let's first understand why we need it.

1. Creating Threads Manually

We already know how to create a thread using the Thread class. We can provide a task using a lambda expression and start the thread.

For example:

public class ManualThreadExample {

    public static void main(String[] args) {

        for (int i = 1; i <= 5; i++) {

            int taskNumber = i;

            Thread thread = new Thread(() -> {
                System.out.println(
                    "Task " + taskNumber + " is running"
                );
            });

            thread.start();
        }
    }
}

Let's understand what is happening here.

Each task gets its own thread in this example. The threads can run independently, and the order of their output may vary.

This approach is perfectly valid for simple examples. We have used it throughout our course.

However, let's think about what happens when an application has hundreds or thousands of tasks.

2. Why Creating Every Thread Manually Can Become a Problem

Problem 1: Too Many Threads

Imagine an application receives 1,000 tasks.

If we create a new thread for every task, we may end up creating 1,000 threads.

Threads require memory and other system resources. Creating too many threads can put unnecessary pressure on the system and affect application performance.

More threads do not automatically mean better performance.

Problem 2: Managing Threads Becomes Difficult

When we create threads manually, we are responsible for managing their lifecycle.

For example, we may need to think about:

As the application grows, managing all these details becomes complicated.

Problem 3: Task and Thread Management Are Mixed Together

Consider our earlier example.

We are writing the task and also deciding how to create and start its thread.

But these are actually two different responsibilities:

It would be much cleaner if we could define our tasks separately and let another component manage their execution.

3. An Everyday Example

Imagine a restaurant that receives 100 customer orders.

The restaurant does not need to hire a completely new chef for every order.

Instead, it has a team of chefs. A manager receives the orders and assigns work to the available chefs.

The manager helps with:

We can think of the Executor Framework in a similar way.

Instead of creating a new thread for every task ourselves, we can submit tasks to an execution manager.

The execution manager takes responsibility for arranging how those tasks are executed using threads.

4. What Does the Executor Framework Do?

The Executor Framework is a set of Java classes and interfaces that helps us manage task execution using threads.

Its biggest benefit is that it separates the work we want to perform from the management of threads that perform that work.

Think of the process like this:

Without the Executor Framework

We create a task.

↓

We create a Thread.

↓

We start and manage the Thread.

With the Executor Framework

We create a task.

↓

We submit the task to an execution manager.

↓

The manager arranges its execution using threads.

Notice the difference?

We focus on defining the work. The framework takes care of managing its execution.

5. Does the Executor Framework Eliminate Threads?

No!

This is an important point to understand.

The Executor Framework still uses threads to execute tasks. It simply provides a more organized way to manage them.

For example, an execution manager may maintain a group of reusable threads. When a new task arrives, it can assign that task to an available thread.

This means we do not necessarily need to create a brand-new thread for every task.

We will learn more about this concept when we study Thread Pools in Class 28.

6. When Should We Use the Executor Framework?

The Executor Framework is especially useful when:

For a very small program, manually creating a thread may be perfectly fine.

But as an application grows, the Executor Framework gives us a more manageable approach.

7. What Will We Learn Next?

Now that we understand why the Executor Framework is useful, let's look at the actual Java interfaces that make it work.

In the next class, we will learn about:

We will also write our first program using the Executor Framework.

Don't worry. We will understand everything step by step!

Test Your Understanding

Let's see how well you understood this class!

Question 1: What is one problem with creating a new thread for every task?

Question 2: What is the main purpose of the Executor Framework?

Question 3: What does separating tasks from thread management mean?

Question 4: Does the Executor Framework still use threads?

Question 5: Which of the following is a benefit of the Executor Framework?

Class Summary

In this class, we understood why Java provides the Executor Framework.

  • Creating a new thread for every task can consume system resources.
  • Manually managing many threads can become complicated.
  • Task definition and thread management are two separate responsibilities.
  • The Executor Framework helps separate these responsibilities.
  • It still uses threads, but provides a more organized way to manage task execution.

Remember: Focus on what work needs to be done. Let the Executor Framework help manage how that work gets executed.

Next Class: Introduction to Executor and ExecutorService

We now understand why we need the Executor Framework. In the next class, we will explore its two important interfaces: Executor and ExecutorService.

We will write a simple Java program and learn how to submit tasks without manually creating and starting threads.

Let's move from understanding the idea to using it in Java!

0% Completed

You have completed 26 out of 46 classes.