coroutine A long time ago I knew this thing, but Java did not, so I did not know much about it, recently in learning Python see coroutine, make a record.
Concepts
Speaking of coroutine is generally associated with processes and threads, usually please compare the three as follows.
- Process: an instance of program execution, a process contains at least one thread, and switching between different processes is costly.
- Thread: the basic unit of CPU scheduling, an entity of a process, the context switching cost of threads is smaller than that of processes.
- coroutine : a user-state lightweight thread, a thread can contain more than one coroutine .
The biggest advantage of coroutine is its extremely high execution efficiency. Because subroutine switching is not thread switching, but controlled by the program itself, there is no overhead of thread switching, and the more threads there are compared to multiple threads, the more obvious the performance advantage of coroutine is.
The second major advantage is that there is no need for the lock mechanism of multi-threading, because there is only one thread, and there is no conflict of writing variables at the same time. In coroutine, the shared resources are controlled without locking, and only the state needs to be judged, so the execution efficiency is much higher than multi-threading.
Coroutine in Python
generators generator and yield keywords
If a function definition contains the yield keyword, then it is a generator function.
The syntax of yield is that it pauses the function here at yield and returns the value of the expression after yield (default is None) until it is called again by the next() method, which continues from the last paused yield code. When there is no way to continue next(), an exception is thrown, which can be handled by the for loop.
Each generator can execute the send() method, which sends data to the yield statement inside the generator; Python’s support for coroutines is implemented through the generator.
Look at an example of a producer and a consumer, where the producer produces a message and then yields to the consumer to consume it, and the consumer executes and jumps back to the producer to continue producing, all within a single thread.
|
|
Output:
@asyncio.coroutine and yield from
@asyncio.coroutine
marks a generator as a coroutine, and yield from waits for the return of another coroutine. asyncio
is a time-loop-based asynchronous IO module introduced in Python 3.4.
The programming model of asyncio
is a message loop. We get a reference to an EventLoop directly from the asyncio
module, and then throw the coroutine that needs to be executed into the EventLoop to execute it, which implements asynchronous IO.
|
|
Output.
|
|
The environment here is Python 3.8, and you can see the warning that @coroutine
is not recommended for newer versions, and that you can use async def
to define the coroutine.
async and await
|
|
Output.
coroutine is suitable for IO-intensive, not CPU-intensive applications.
Why Java doesn’t have a coroutine
In the current release of Java, there is no coroutine yet. The usual point of using coroutine is to save the overhead of creating and switching threads, but there have always been other solutions in Java, such as
- the availability of non-blocking I/O client-server frameworks such as Netty.
- thread pools solve the overhead of thread creation and destruction.
- The JDK also has complete tools like JUC for asynchronous programming.
The biggest benefit of using coroutine in other languages is that it is simple and elegant to write, synchronous to write and asynchronous to run. In contrast Java’s asynchronous threads are much more complex to write, and Java has always been criticized for being too cumbersome.
Java is also currently pushing the development of a coroutine library, the Loom project, which is still in development.