The 3 methods in concurrent.futures
- silviamazzoni
- Apr 5
- 3 min read
Updated: Apr 9
The map method confuses me, so I typically use the submit method. I am hoping ChatGPT helps me understand it better, so I know when to use it. Help me, ChatGPT... After reading what is below i know why I use submit -- it returns results as they are ready -- combined with as_completed. On the other hand, order matters in map and it returns results only when all are ready. I guess you would use map in a workflow when you can go to the next step only when all processes in this step are done...
Let's dive deeper into the three main methods you use with concurrent.futures executors:
.submit()
.map()
.as_completed()
Each has its strengths depending on how you want to run and manage parallel tasks — and they all work with both ThreadPoolExecutor and ProcessPoolExecutor.
✅ 1. .submit()
🔹 What it does:
Submits a single task to the executor and returns a Future object.
You can use .submit() multiple times to queue up several tasks.
🔧 Syntax:
future = executor.submit(function, arg1, arg2, ...)
📌 Features:
Allows fine-grained control over each task
Returns immediately with a Future object
You can later use .result() to get the result
🧪 Example:
from concurrent.futures import ThreadPoolExecutor
def square(x):
return x * x
with ThreadPoolExecutor() as executor:
futures = [executor.submit(square, i) for i in range(5)]
for future in futures:
print(future.result())
✅ 2. .map()
🔹 What it does:
Submits multiple tasks at once by applying a function to a sequence of inputs (like map()).
Returns the results in the original order.
🔧 Syntax:
results = executor.map(function, iterable)
📌 Features:
Easy one-liner for mapping a function over multiple inputs
Automatically blocks until all tasks are done
No access to individual Future objects
🧪 Example:
from concurrent.futures import ProcessPoolExecutor
def cube(x):
return x ** 3
with ProcessPoolExecutor() as executor:
results = executor.map(cube, [1, 2, 3, 4])
print(list(results)) # Output: [1, 8, 27, 64]
✅ 3. .as_completed()
🔹 What it does:
Works with a list of Future objects (usually from .submit()).
Yields each future as soon as it finishes, not in the order submitted.
🔧 Syntax:
from concurrent.futures import as_completed
for future in as_completed(futures):
result = future.result()
📌 Features:
Ideal for cases where you want results as soon as they’re ready
Useful for long-running tasks where early results can be processed immediately
Better performance for streaming/interactive systems
🧪 Example:
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import random
def task(x):
sleep_time = random.uniform(0.5, 2.0)
time.sleep(sleep_time)
return f"Task {x} completed in {sleep_time:.2f} sec"
with ThreadPoolExecutor() as executor:
futures = [executor.submit(task, i) for i in range(5)]
for future in as_completed(futures):
print(future.result())
🧾 Summary Comparison
Feature | .submit() | .map() | as_completed() |
Returns Futures? | ✅ Yes | ❌ No (returns results) | ✅ Works with Futures |
Order of results | You control the order | Preserves input order | Order based on task completion |
Use case | Full control, custom logic | Quick batch processing | Early result processing |
Can handle args? | ✅ Yes (any args) | ✅ Yes (1 iterable per param) | ✅ Yes (via submit) |
🧠 When to Use Each
Use .submit() when:
You need flexibility
You want to manage each task individually
You need to cancel or monitor specific tasks
Use .map() when:
You want a quick, clean way to apply a function to a list of inputs
You don't need to manage tasks individually
Use as_completed() when:
You want to handle results as soon as they’re ready
Tasks vary in execution time
You’re building responsive or streaming workflows
📊 concurrent.futures Execution Flow
┌─────────────────────────────┐
│ Executor (with) │
│ ThreadPool or ProcessPool │
└─────────────────┬───────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
.submit(fn, arg) .map(fn, iterable) .submit(...) + as_completed()
│ │ │
┌───────▼────────────┐ ┌────▼─────┐ ┌──────────▼────┐
│ Returns Future objects │ │ Executes fn(x) │ │ Returns Future as │
│ for each task │ │ for each item │ │ soon as it's done │
└────────────────────┘ └──────────┘ └───────────────┘
│
┌───────▼────────┐
│ Results returned in │
│ original input order │
└────────────────┘
Comments