Maison >développement back-end >tutoriel php >Explication détaillée du contenu de la coroutine PHP
Cet article partage avec vous le contenu sur PHP Xiecheng. Il a une certaine valeur de référence. J'espère qu'il pourra aider les amis dans le besoin.
Nous savons que le multi-processus et le multi-thread sont des moyens efficaces pour atteindre la concurrence. Cependant, la surcharge de ressources de changement de contexte du multi-processus est trop élevée ; la surcharge du multi-threading est beaucoup plus petite, ce qui est également la pratique courante actuelle, mais son contrôle est dans le noyau, de sorte que l'utilisateur (programmeur) perd le contrôle de le code et le thread La commutation de contexte entraîne également une certaine surcharge. A cette époque, afin de résoudre les problèmes ci-dessus, le concept de « coroutine » est né. Vous pouvez considérer les coroutines comme des threads plus légers. Ce type de thread est appelé « thread de l’espace utilisateur ». Les coroutines ont les deux caractéristiques suivantes :
Collaboration. Parce qu'il s'agit d'une stratégie de planification écrite par le programmeur lui-même, elle passe par collaboration plutôt que par préemption
La création, la commutation et la destruction sont effectuées en mode utilisateur
Le support PHP des coroutines est basé sur le générateur itératif, ajoutant la fonction de renvoi de données au générateur (l'appelant envoie des données à la fonction générateur appelée). Cela transforme la communication unidirectionnelle du générateur vers l'appelant en une communication bidirectionnelle entre les deux.
La notion d'itérateur ne sera pas décrite ici. Jetons un coup d'œil à un itérateur que nous avons nous-mêmes implémenté.
class MyIterator implements Iterator { private $var = array(); public function __construct($array) { if (is_array($array)) { $this->var = $array; } } public function rewind() { // 第一次迭代时候会执行(或调用该方法的时候),后面的迭代将不会执行。 echo "rewinding\n"; reset($this->var); } 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; } public function next() { // 最后执行,就是执行完下面sleep(2)后再执行。(执行了next本次迭代才算结束) $var = next($this->var); echo "next: $var\n"; return $var; } public function valid() { // 当valid返回false的时候迭代结束 $var = $this->current() !== false; echo "valid: {$var}\n"; return $var; } } $values = array(1,2,3,4); $it = new MyIterator($values); foreach ($it as $a => $b) { // 进行迭代(每次迭代,会依次执行以下方法: rewind(特别之处见上面解释), valid, current, key, next) print "=====\n"; sleep(2); }
Sortie :
rewinding current: 1 // 因为valid里面调用了current, 这里current出来一次 valid: 1 current: 1 key: 0 ===== next: 2 current: 2 valid: 1 current: 2 key: 1 ===== next: 3 current: 3 valid: 1 current: 3 key: 2 ===== next: 4 current: 4 valid: 1 current: 4 key: 3 ===== next: current: valid: // valid返回false,迭代结束
La méthode de yeild est un générateur (le générateur implémente l'interface Iterator, c'est-à-dire , un générateur a les caractéristiques d’un itérateur). L'implémentation du générateur est la suivante :
function xrange($start, $end, $step = 1) { for ($i = $start; $i <= $end; $i += $step) { echo $i . "\n"; yield; } } // foreach方式 foreach (xrange(1, 10) as $num) { } $gene = xrange(1, 10); // gene就是一个生成器对象 // current $gene->current(); // 打印1 // next $gene->next(); $gene->current() // 打印2
Sortie :
1 2 3 4 5 6 7 8 9 10 1 2
Remarque :
Le générateur ne peut pas être appelé directement comme une fonction. La méthode d'appel est la suivante :
1. pour chaque personne2. envoyer($value) 3. actuel / suivant...function task1 () { for ($i = 1; $i <= 10; ++$i) { echo "This is task 1 iteration $i.\n"; yield;// 遇到yield就会主动让出CPU的执行权; } } $a = task1(); $a->current(); // 执行第一次迭代 $a->send(1); // 唤醒当时让出CPU执行权的yieldSortie :
This is task 1 iteration 1. This is task 1 iteration 2.Cas d'utilisation 2 : rendement du rendement
// yield返回 function task2 () { for ($i = 1; $i <= 10; ++$i) { echo "This is task 2 iteration $i.\n"; yield "lm$i"; // 遇到yield就会主动让出CPU的执行权,for暂停执行, 然后返回"lm"。放在yield后面的值就是返回值 } } $a = task2(); $res = $a->current(); // 第一次迭代, 遇到yield返回 var_dump($res); $res = $a->send(1); // 唤醒yield, for继续执行,遇到yield返回。 var_dump($res);Sortie :
This is task 2 iteration 1. string(3) "lm1" This is task 2 iteration 2. string(3) "lm2"Cas d'utilisation 3 : le rendement reçoit une valeur
function task3 () { for ($i = 1; $i <= 10; ++$i) { echo "This is task 3 iteration $i.\n"; $getValue = yield;// 遇到yield就会主动让出CPU的执行权;send后,将send值赋值给getValue echo $getValue . " "; } } $a = task3(); $a->current(); $a->send("aa"); // 唤醒yield,并将"aa"值赋值给$getValue变量Sortie :
This is task 3 iteration 1. aa This is task 3 iteration 2.Cas d'utilisation 4 : la réception et le retour du rendement sont écrits ensemble
function task4 () { for ($i = 1; $i <= 10; ++$i) { echo "This is task 4 iteration $i.\n"; $ret = yield "lm$i"; // yield, 然后返回lm$i; 当send时,将send过来的值赋值给$ret; echo $ret; } } $a = task4(); var_dump($a->current()); // 返回lm1 var_dump($a->send("hhh ")); // 先唤醒yield, 将"hhh "赋值给$ret,再返回lm2 var_dump($a->send("www ")); // 先唤醒yield, 将"www "赋值给$ret,再返回lm3Sortie :
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"Recommandations associées :
Comment utiliser les classes et interfaces abstraites en PHP (code)
Implémentation du code de la pagination PHP et vérification régulière
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!