This article for you to share about the PHP co-formed content, there is a certain reference value, hoping to help the needy friends.
Concept
We know that multi-process and multithreading are effective ways to achieve concurrency. However, the context switching resource overhead of multi-process is too large, the multithreading cost is much smaller than the current mainstream practice, but its control in the kernel, so that the user (programmer) lost control of the code, and the context of the thread switching also has a certain cost. In order to solve the above problems, the concept of "Coroutine" is produced. You can interpret the process as a lighter-weight thread. This thread is called a "user space thread". The following two features are available:
Collaborative. Because it is a scheduling policy written by the programmer itself, it switches through collaboration rather than preemption.
Create, switch and destroy in User Configuration
PHP support for the co-process is based on the iterative generator , adding the ability to send data back to the generator (the caller sends the data to the called generator function). This transforms the one-way communication between the generator and the caller into two-way communication between the two.
Iterators
The concept of iterators is not discussed here. Let's look at an iterator we've implemented ourselves.
Class Myiterator implements iterator{private $var = Array (); Public function __construct ($array) {if (Is_array ($array)) {$this->var = $array; }} Public Function rewind () {//At the time of the first iteration (or when the method is called), subsequent iterations will not be executed. echo "rewinding\n"; Reset ($this->var); The public Function current () {$var = current ($this->var); echo "Current: $var \ n"; return $var; Public Function key () {$var = key ($this->var); echo "key: $var \ n"; return $var; The public function next () {//Last executes, which is done after sleep (2) is executed. $var = Next ($this->var) When the next iteration is completed; echo "Next: $var \ n"; return $var; The public function valid () {//valid returns False when the iteration ends $var = $this->current ()!== false; echo "valid: {$var}\n"; return $var; }} $values = Array (1,2,3,4), $it = new Myiterator ($values), and foreach ($it as $a + $b) {//iterate (each iteration, in turn, performs the following methods: Rewind (See above for special explanations), valid, current, key, next) print "=====\n"; Sleep (2);}
Output:
Rewindingcurrent:1 //Because valid inside called the current, here current comes out once valid:1current:1key:0=====next:2current:2valid: 1current:2key:1=====next:3current:3valid:1current:3key:2=====next:4current:4valid:1current:4key:3=====next:cu Rrent:valid: //valid return False, end of iteration
Generator
The Yeild method is a generator (the generator implements the iterator interface, which is the feature of a generator with iterators). The implementation of the generator is as follows:
function xrange ($start, $end, $step = 1) {for ($i = $start; $i <= $end; $i + = $step) { echo $i. "\ n"; yield; }} The foreach mode foreach (xrange (1, ten) as $num) { } $gene = xrange (1, ten);//Gene is a Generator object//Current$gene->current ();
//print 1//next$gene->next (); $gene->current () //Print 2
Output:
1234567891012
Builder each method is detailed to see the document: http://php.net/manual/zh/class.generator.php
Attention:
The generator cannot be called directly like a function, and the method is called as follows:
1. Foreach He
2. Send ($value)
3. Current/next ...
Yield
The yield syntax is very flexible, and we use the following example to let you understand the use of yield syntax.
Use Case 1: Give Up CPU execution
function Task1 () {for ($i = 1; $i <=; + + $i) { echo "This is Task 1 iteration $i. \ n"; yield;//meet yield will take the initiative to give up the CPU execution;} } $a = Task1 (); $a->current (); Perform the first iteration of $a->send (1); Wake up at that time yield of the CPU execution right
Output:
This is Task 1 iteration 1.This is task 1 Iteration 2.
Return of use case 2:yield
Yield returns function Task2 () {for ($i = 1; $i <=; + + $i) { echo "This is Task 2 iteration $i. \ n"; Yield "lm$i"; When yield is encountered, it voluntarily yields the CPU execution, for suspending execution and then returning "LM". The value placed after yield is the return value }} $a = Task2 (); $res = $a->current (); The first iteration, encountered yield return var_dump ($res); $res = $a->send (1); Wake yield, for continue execution, encountered yield return. Var_dump ($res);
Output:
This is Task 2 iteration 1.string (3) "LM1" The IS Task 2 iteration 2.string (3) "LM2"
Use case 3:yield receive value
function Task3 () {for ($i = 1; $i <=; + + $i) { echo "This is task 3 iteration $i. \ n"; $getValue = yield;//will voluntarily give up the CPU execution when it encounters yield, and after send, assign the send value to the GetValue Echo $getValue. " "; }} $a = Task3 (); $a->current (); $a->send ("AA"); Wake yield and assign the "AA" value to the $getvalue variable
Output:
This is Task 3 iteration 1.aa This is task 3 iteration 2.
Use case 4:yeild receive and return are written together
function Task4 () {for ($i = 1; $i <=; + + $i) { echo "This is Task 4 iteration $i. \ n"; $ret = yield "lm$i"; Yield, and then return lm$i; When send, assign the value sent to $ret; echo $ret; }} $a = Task4 (); Var_dump ($a->current ()); Return to Lm1var_dump ($a->send ("HHH")); The yield is awakened first, the "HHH" is assigned to the $ret, and then the Lm2var_dump ($a->send ("www") is returned; First wake yield, assign "www" to $ret, and return to LM3
Output:
This is Task 4 iteration 1.string (3) "LM1" HHH this is Task 4 Iteration 2. String (3) "LM2" www This is Task 4 Iteration 3. String (3) "LM3"