博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PHP协程
阅读量:6823 次
发布时间:2019-06-26

本文共 2552 字,大约阅读时间需要 8 分钟。

协程

“协程”就是用户态的线程

要理解是什么是“用户态的线程”,必然就要先理解什么是“内核态的线程”。 内核态的线程是由操作系统来进行调度的,在切换线程上下文时,要先保存上一个线程的上下文,然后执行下一个线程,当条件满足时,切换回上一个线程,并恢复上下文。 协程也是如此,只不过,用户态的线程不是由操作系统来调度的,而是由程序员来调度的,是在用户态的 -- 摘自

关于“用户态线程”,我们用个小例子来加深理解

我们有两个函数 task1,task2,我们来手动调度它们的执行顺序,比如在task1执行一半的时候去执行task2,两个或者多个函数之间交替执行(这就是协程的概念)。

我们来个正常的函数调用方式:

可想而知,以上的输出肯定是:

task1函数 执行第1task1函数 执行第2task2函数 执行第1task2函数 执行第2

但是我想在程序输出task1函数 执行1之后就输出task2函数 执行1怎么办?

这个时候 就派上用场了,PHP里的协程是需要借助 来完成的。记住, 不是协程,而是协程需要借助 的特性来实现。

current();$task2->current();

以上输出:

task1函数 执行1task2函数 执行1

很好,以上结果达到了我们的预期。但是怎么让函数里的代码往下执行呢?

调用生成器的next方法:

$task1->next();$task2->next();

最后你将看到的输出结果是两个函数交替执行输出的:

task1函数 执行1task2函数 执行1task1函数 执行2task2函数 执行2

小段总结

以上的代码实现可以抽象出两个概念,任务调度任务就是task函数,调度就是我们怎么去调用这些task函数

调度器和任务生成器

上一个小段总结里有两个概念叫任务调度,我们简单的封装个任务生成器和调度器

// 任务生成器$createTask = (function () {    $tasks = [];    return function ($callback) use (&$tasks) {        $task = [            'task' => $callback(),            'id' => count($tasks) + 1,        ];        array_push($tasks, $task);        return $task;    };})();// 调度器function schedule($tasks){    $first = [];    while (!empty($tasks)) {        $task = array_shift($tasks);        if (!array_key_exists($task['id'], $first)) {            $first[$task['id']] = true;            $task['task']->current();        } else {            $task['task']->next();        }        if (!$task['task']->valid()) {            unset($tasks[$k]);        } else {            array_push($tasks, $task);        }    }}

使用

$tasks = [    $createTask(function () {        echo "任务1 执行第1次\n";        yield;        echo "任务1 执行第2次\n";    }),    $createTask(function () {        echo "任务2 执行第1次\n";        yield;        echo "任务2 执行第2次\n";    })];schedule($tasks);

输出结果:

任务1 执行第1次任务2 执行第1次任务1 执行第2次任务2 执行第2次

可以从结果看出,调度器已经实现了多个任务之间进行协作。

网络请求

现在有个需求!就是任务在遇到网络请求的时候,我们无需等待网络请求的响应结果,而是遇到网络请求的时候,把这个任务挂起,然后去执行其它任务,等网络请求收到响应结果了再通知我们处理

这时候需要我们用到非阻塞IO调用相关技术,涉及到系统内核层面,想了解可以点击

在PHP里我们需要安装个扩展eio,大家自行安装

pecl install eio

编码:

$tasks = [    $createTask(function () {        echo "任务1 执行第1次\n";        yield;        echo "任务1 执行第2次\n";    }),    $createTask(function () {        echo "任务2 执行第1次\n";        eio_custom(function () {            return file_get_contents('https://segmentfault.com/');        }, EIO_PRI_DEFAULT, function ($data, $ret) {            echo "请求完成\n";        });                yield;        echo "任务2 执行第2次\n";    })];schedule($tasks);eio_event_loop();

任务2 执行第1次的时候,遇到网络请求,我们把请求任务交给系统内核,然后切换到其它任务去,等请求任务完成后回调我们传入的函数。

输出结果:

任务1 执行第1次任务2 执行第1次任务1 执行第2次任务2 执行第2次任务2 执行第1次的请求完成

完!

转载地址:http://fhrzl.baihongyu.com/

你可能感兴趣的文章
毕业论文一次性修改所有字母和数字的字体
查看>>
vsphere5.2.安装部署VMware ESXi 5 上 视频共享
查看>>
impala1.2.3 udf问题
查看>>
数据仓库专题23-原则!原则!原则!
查看>>
细节决定成败2: 链路负载均衡遇到IPS
查看>>
LigerUI中通过加载服务端数据进行表格的分页显示
查看>>
Hyper-V 2016 系列教程40 使用 PowerShell 实现虚拟机自动化和管理虚拟机
查看>>
手把手教你 MongoDB 的安装与详细使用(二)
查看>>
小型机业务迁移到虚拟化PC服务器上之性能换算分析
查看>>
根据Web服务器记录来追击黑客
查看>>
Java类和对象的初始化顺序
查看>>
Oracle 11g RAC 二节点root.sh执行报错故障一例
查看>>
ocs的部署与应用(一)
查看>>
Python黑客编程之信息收集
查看>>
Django+ PowerShell 管理AD系统
查看>>
leopard ich7 alc 888 driver
查看>>
开始学习Docker啦--容器理论知识(一)
查看>>
流数据库 概率计算概念 - PipelineDB-Probabilistic Data Structures & Algorithms
查看>>
Java注解不完全总结
查看>>
解决“此电脑上没有安装True Speech声音解码器”的方法
查看>>