Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between using the method ThreadPoolExecutor.shutdown(wait=True), shutdown(wait=False) and without using this one?

I can't understand difference. Help me to watch this difference. And what about ProcessPoolExecutor, is his behavior the same?

def func(task):
    do_something(task)

tasks = [task for i in range(12)]
executor = ThreadPoolExecutor(4)
executor.map(func, tasks)
executor.shutdown(wait=True)  # ok, here the main thread waits for others

tasks = [task for i in range(12)]
executor = ThreadPoolExecutor(4)
executor.map(func, tasks)
executor.shutdown(wait=False)  # here it doesn't wait and what can happens bad?

tasks = [task for i in range(12)]
executor = ThreadPoolExecutor(4)
executor.map(func, tasks)  # if i don't call shutdown ?
like image 719
r45i Avatar asked Feb 09 '15 19:02

r45i


People also ask

How does ThreadPoolExecutor work in Python?

ThreadPoolExecutor is an Executor subclass that uses a pool of threads to execute calls asynchronously. An Executor subclass that uses a pool of at most max_workers threads to execute calls asynchronously.

Why do we use ThreadPoolExecutor?

Use the ThreadPoolExecutor class when you need to execute tasks that may or may not take arguments and may or may not return a result once the tasks are complete. Use the ThreadPoolExecutor class when you need to execute different types of ad hoc tasks, such as calling different target task functions.

How do you wait for ThreadPoolExecutor?

You can wait for a task to finish in a ThreadPoolExecutor by calling the wait() module function.

Is ThreadPoolExecutor concurrent?

From Python 3.2 onwards a new class called ThreadPoolExecutor was introduced in Python in concurrent. futures module to efficiently manage and create threads.


1 Answers

From the docs:

If wait is True then this method will not return until all the pending futures are done executing and the resources associated with the executor have been freed. If wait is False then this method will return immediately and the resources associated with the executor will be freed when all pending futures are done executing. Regardless of the value of wait, the entire Python program will not exit until all pending futures are done executing.

This covers the first two examples.

For the third one, since ThreadPoolExecutor adheres to the "context manager" protocol you can use it along the with statement in order to have the shutdown method automatically called for as soon as execution exits the with block.

The default is True if you omit the parameter - or if you use it as a context manager, so using it inside the with block is useless no matter the value of wait.

[edit]

i edited code. See pls, there are my final questions

You only call the shutdown method if you want to explicitly release all resources and ensure no new calls to submit or map will succeed. If you don't call shutdown (or use ThreadPoolExecutor as a context manager), resources may be released only when the entire Python program exits (and it will not exit until all pending futures are done).

Calling shutdown with wait==True or using ThreadPoolExecutor as a context manager will block until all pending futures are done executing.

The only use case I can think of for calling shutdown explicitly is:

executor = ThreadPoolExecutor(4)
try:
    executor.map(func, tasks)
finally:
    executor.shutdown(wait=False)

To give some context, this is the code snippet from the first version of this question:

def func(task):
    do_something(task)

tasks = [task for i in range(12)]
with ThreadPoolExecutor(4) as executor:
    executor.map(func, tasks)
    executor.shutdown(wait=True)  # what is happening here?

tasks = [task for i in range(12)]
with ThreadPoolExecutor(4) as executor:
    executor.map(func, tasks)
    executor.shutdown(wait=False)  # what is happening here?

tasks = [task for i in range(12)]
with ThreadPoolExecutor(4) as executor:
    executor.map(func, tasks)  # and without shutdown()?

Note that tasks = [task for i in range(12)] is redundant - you can use just executor.map(func, range(12)) as well.

like image 79
Paulo Scardine Avatar answered Oct 24 '22 04:10

Paulo Scardine