<Futr> = <Exec>.submit(<func>, <arg_1>, ...) # Creates a thread and returns its Future obj.
<Exec>.shutdown() # Waits for all submitted threads to finish.
<Exec>.shutdown() # Waits for all threads to finish executing.
```
```python
<bool> = <Future>.done() # Checks if the thread has finished executing.
<obj> = <Future>.result(timeout=None) # Waits for thread to finish and returns result.
<obj> = <Future>.result(timeout=None) # Raises TimeoutError after 'timeout' seconds.
<bool> = <Future>.cancel() # Cancels or returns False if running/finished.
<iter> = as_completed(<coll_of_Futures>) # `next(<iter>)` returns next completed Future.
```
@ -2306,8 +2306,8 @@ with <lock>: # Enters the block by calling acq
Coroutines
----------
* **Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t use as much memory.**
* **Coroutine definition starts with `'async'` and its call with `'await'`.**
* **Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t consume as much memory.**
* **Coroutine definition starts with `'async'` and its call with `'await'` keyword.**
* **Use `'asyncio.run(<coroutine>)'` to start the first/main coroutine.**
```python
@ -2316,7 +2316,7 @@ import asyncio as aio
```python
<coro> = <async_function>(<args>) # Creates a coroutine by calling async def function.
<obj> = await <coroutine> # Starts the coroutine and waits for its result.
<obj> = await <coroutine> # Starts the coroutine. Returns its result or None.
<task> = aio.create_task(<coroutine>) # Schedules it for execution. Always keep the task.
<obj> = await <task> # Returns coroutine's result. Also <task>.cancel().
<li><strong>Use <codeclass="python hljs"><spanclass="hljs-string">'kwargs=<dict>'</span></code> to pass keyword arguments to the function.</strong></li>
<li><strong>Use <codeclass="python hljs"><spanclass="hljs-string">'daemon=True'</span></code>, or the program won't be able to exit while the thread is alive.</strong></li>
</ul>
<div><h3id="lock">Lock</h3><pre><codeclass="python language-python hljs"><lock> = Lock/RLock() <spanclass="hljs-comment"># RLock can only be released by acquirer.</span>
<lock>.acquire() <spanclass="hljs-comment"># Waits for the lock to be available.</span>
<lock>.release() <spanclass="hljs-comment"># Makes the lock available again.</span>
<div><h3id="lock">Lock</h3><pre><codeclass="python language-python hljs"><lock> = Lock/RLock() <spanclass="hljs-comment"># RLock can only be released by acquirer thread.</span>
<lock>.acquire() <spanclass="hljs-comment"># Blocks (waits) until lock becomes available.</span>
<lock>.release() <spanclass="hljs-comment"># It makes the acquired lock available again.</span>
</code></pre></div>
<div><h4id="or-1">Or:</h4><pre><codeclass="python language-python hljs"><spanclass="hljs-keyword">with</span><lock>: <spanclass="hljs-comment"># Enters the block by calling acquire() and</span>
... <spanclass="hljs-comment"># exits it with release(), even on error.</span>
<div><h4id="or-1">Or:</h4><pre><codeclass="python language-python hljs"><spanclass="hljs-keyword">with</span><lock>: <spanclass="hljs-comment"># Enters the block by calling method acquire().</span>
... <spanclass="hljs-comment"># Exits by calling release(), even on error.</span>
</code></pre></div>
<div><h3id="semaphoreeventbarrier">Semaphore, Event, Barrier</h3><pre><codeclass="python language-python hljs"><Semaphore> = Semaphore(value=<spanclass="hljs-number">1</span>) <spanclass="hljs-comment"># Lock that can be acquired by 'value' threads.</span>
<Queue>.put(<obj>)<spanclass="hljs-comment"># Call blocks until queue stops being full.</span>
<Queue>.put_nowait(<obj>)<spanclass="hljs-comment"># Raises queue.Full exception if queue is full.</span>
<obj> = <Queue>.get() <spanclass="hljs-comment"># Call blocks until queue stops being empty.</span>
<obj> = <Queue>.get_nowait() <spanclass="hljs-comment"># Raises queue.Empty exception if it's empty.</span>
</code></pre></div>
<div><h3id="threadpoolexecutor">Thread Pool Executor</h3><pre><codeclass="python language-python hljs"><Exec> = ThreadPoolExecutor(max_workers=<spanclass="hljs-keyword">None</span>) <spanclass="hljs-comment"># Also `with ThreadPoolExecutor() as <name>: …`.</span>
<Futr> = <Exec>.submit(<func>, <arg_1>, ...) <spanclass="hljs-comment"># Creates a thread and returns its Future obj.</span>
<Exec>.shutdown() <spanclass="hljs-comment"># Waits for all submitted threads to finish.</span>
<Exec>.shutdown() <spanclass="hljs-comment"># Waits for all threads to finish executing.</span>
</code></pre></div>
<pre><codeclass="python language-python hljs"><bool> = <Future>.done() <spanclass="hljs-comment"># Checks if the thread has finished executing.</span>
<obj> = <Future>.result(timeout=<spanclass="hljs-keyword">None</span>) <spanclass="hljs-comment"># Waits for thread to finish and returns result.</span>
<obj> = <Future>.result(timeout=<spanclass="hljs-keyword">None</span>) <spanclass="hljs-comment"># Raises TimeoutError after 'timeout' seconds.</span>
<bool> = <Future>.cancel() <spanclass="hljs-comment"># Cancels or returns False if running/finished.</span>
<iter> = as_completed(<coll_of_Futures>) <spanclass="hljs-comment"># `next(<iter>)` returns next completed Future.</span>
<li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be <ahref="#pickle">pickable</a>, queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via <codeclass="python hljs"><spanclass="hljs-string">'if __name__ == "__main__": ...'</span></code>.</strong></li>
<li><strong>Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t use as much memory.</strong></li>
<li><strong>Coroutine definition starts with <codeclass="python hljs"><spanclass="hljs-string">'async'</span></code> and its call with <codeclass="python hljs"><spanclass="hljs-string">'await'</span></code>.</strong></li>
<li><strong>Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t consume as much memory.</strong></li>
<li><strong>Coroutine definition starts with <codeclass="python hljs"><spanclass="hljs-string">'async'</span></code> and its call with <codeclass="python hljs"><spanclass="hljs-string">'await'</span></code> keyword.</strong></li>
<li><strong>Use <codeclass="python hljs"><spanclass="hljs-string">'asyncio.run(<coroutine>)'</span></code> to start the first/main coroutine.</strong></li>
<pre><codeclass="python language-python hljs"><coro> = <async_function>(<args>) <spanclass="hljs-comment"># Creates a coroutine by calling async def function.</span>
<obj> = <spanclass="hljs-keyword">await</span><coroutine><spanclass="hljs-comment"># Starts the coroutine and waits for its result.</span>
<obj> = <spanclass="hljs-keyword">await</span><coroutine><spanclass="hljs-comment"># Starts the coroutine. Returns its result or None.</span>
<task> = aio.create_task(<coroutine>) <spanclass="hljs-comment"># Schedules it for execution. Always keep the task.</span>
<obj> = <spanclass="hljs-keyword">await</span><task><spanclass="hljs-comment"># Returns coroutine's result. Also <task>.cancel().</span>