php基于协程实现异步的方法分析
时间:2022-07-27
本文章向大家介绍php基于协程实现异步的方法分析,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
本文实例讲述了php基于协程实现异步的方法。分享给大家供大家参考,具体如下:
github上php的协程大部分是根据这篇文章实现的:http://nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html。
它们最终的结果都是把回调变成了优雅的顺序执行的代码,但还是阻塞的,不是真正的异步。
比如最热门的:https://github.com/recoilphp/recoil
先安装:
composer require recoil/recoil
执行:
<?php
//recoil.php
include __DIR__ . '/vendor/autoload.php';
use RecoilReactReactKernel;
$i = 100000;
ReactKernel::start(task1());
ReactKernel::start(task2());
function task1(){
global $i;
echo "wait start" . PHP_EOL;
while ($i-- 0) {
yield;
}
echo "wait end" . PHP_EOL;
};
function task2(){
echo "Hello " . PHP_EOL;
yield;
echo "world!" . PHP_EOL;
}
结果:
wait start //等待若干秒 wait end Hello world!
我本来是想让两个任务并行,结果两个任务变成了串行,中间等待的时间什么事情都干不了。React响应式的编程是严格禁止这种等待的,所以我就参照unity3d的协程自己写了个php版本的。上代码:
<?php
//Coroutine.php
//依赖swoole实现的定时器,也可以用其它方法实现定时器
class Coroutine
{
//可以根据需要更改定时器间隔,单位ms
const TICK_INTERVAL = 1;
private $routineList;
private $tickId = -1;
public function __construct()
{
$this- routineList = [];
}
public function start(Generator $routine)
{
$task = new Task($routine);
$this- routineList[] = $task;
$this- startTick();
}
public function stop(Generator $routine)
{
foreach ($this- routineList as $k = $task) {
if($task- getRoutine() == $routine){
unset($this- routineList[$k]);
}
}
}
private function startTick()
{
swoole_timer_tick(self::TICK_INTERVAL, function($timerId){
$this- tickId = $timerId;
$this- run();
});
}
private function stopTick()
{
if($this- tickId = 0) {
swoole_timer_clear($this- tickId);
}
}
private function run()
{
if(empty($this- routineList)){
$this- stopTick();
return;
}
foreach ($this- routineList as $k = $task) {
$task- run();
if($task- isFinished()){
unset($this- routineList[$k]);
}
}
}
}
class Task
{
protected $stack;
protected $routine;
public function __construct(Generator $routine)
{
$this- routine = $routine;
$this- stack = new SplStack();
}
/**
* [run 协程调度]
* @return [type] [description]
*/
public function run()
{
$routine = &$this- routine;
try {
if(!$routine){
return;
}
$value = $routine- current();
//嵌套的协程
if ($value instanceof Generator) {
$this- stack- push($routine);
$routine = $value;
return;
}
//嵌套的协程返回
if(!$routine- valid() && !$this- stack- isEmpty()) {
$routine = $this- stack- pop();
}
$routine- next();
} catch (Exception $e) {
if ($this- stack- isEmpty()) {
/*
throw the exception
*/
return;
}
}
}
/**
* [isFinished 判断该task是否完成]
* @return boolean [description]
*/
public function isFinished()
{
return $this- stack- isEmpty() && !$this- routine- valid();
}
public function getRoutine()
{
return $this- routine;
}
}
测试代码:
<?php
//test.php
require 'Coroutine.php';
$i = 10000;
$c = new Coroutine();
$c- start(task1());
$c- start(task2());
function task1(){
global $i;
echo "wait start" . PHP_EOL;
while ($i-- 0) {
yield;
}
echo "wait end" . PHP_EOL;
};
function task2(){
echo "Hello " . PHP_EOL;
yield;
echo "world!" . PHP_EOL;
}
结果:
wait start Hello world! //等待几秒,但不阻塞 wait end
- 集成算法的简单分享
- 5分钟看懂模块 || 数说 · 语言
- Code | Python30个编程技巧!
- 亚马逊AI主任科学家李沐:机器学习简介
- 什么是负载均衡?
- 推荐|14种模型设计帮你改进你的卷积神经网络(CNN)!
- 【源码】Python的开源人脸识别库:离线识别率高达99.38%
- 如何使用深度学习去除人物图像背景
- 开源|人脸检测的C / C ++源代
- Python高性能计算库——Numba
- 最新|官方发布:TensorFlow 数据集和估算器介绍
- 干货 | PyTorch相比TensorFlow,存在哪些自身优势?
- 用TensorFlow和TensorBoard从零开始构建ConvNet(CNN)
- 从零开始:手把手教你安装深度学习操作系统、驱动和各种python库!
- php概述
- php教程
- php环境搭建
- PHP书写格式
- php变量
- php常量
- PHP注释
- php数组
- php字符串 string
- PHP整型 integer
- PHP浮点型 float
- php布尔型
- php数据类型之数组
- php数据类型之对象
- php数据类型之null
- php数据类型之间的转换
- php运算符
- php表达式
- PHP循环控制
- PHP流程控制
- php函数
- php全局变量
- PHP魔术变量
- php命名空间
- php 日期
- PHP包含文件
- php文件
- PHP 文件上传
- php Cookies
- php Sessions
- php email
- php安全email
- php错误处理
- PHP异常处理
- php过滤器
- PHP 高级过滤器
- php json
- php 表单
- PHP MySQL 简介
- PHP 连接 MySQL
- php创建数据库
- php 创建表
- php mysq 插入数据
- PHP MySQL 插入多条数据
- PHP MySQL 预处理语句
- php mysql 读取数据
- php mysql where
- PHP MySQL Order By
- PHP MySQL Update
- PHP MySQL Delete
- php ODBC
- 浙大版《C语言程序设计(第3版)》题目集 习题3-5 三角形判断
- 浙大版《C语言程序设计(第3版)》题目集 练习4-3 求给定精度的简单交错序列部分和
- Linux 如何手动释放Swap、Buffer和Cache
- 浙大版《C语言程序设计(第3版)》题目集 练习4-6 猜数字游戏
- 浙大版《C语言程序设计(第3版)》题目集 练习4-7 求e的近似值
- TypeScript高级类型备忘录(附示例)
- 浙大版《C语言程序设计(第3版)》题目集 练习4-10 找出最小值
- 牛逼!力挺一款实用的 Linux 资源监视工具
- 浙大版《C语言程序设计(第3版)》题目集 练习4-11 统计素数并求和
- 浙大版《C语言程序设计(第3版)》题目集 习题4-1 求奇数和
- Kotlin 使用DSL构建语法结构 看这一篇就够了~
- 浙大版《C语言程序设计(第3版)》题目集 习题4-2 求幂级数展开的部分和
- 2020 年 9 月编程语言排行榜
- 浙大版《C语言程序设计(第3版)》题目集 习题4-3 求分数序列前N项和
- 浙大版《C语言程序设计(第3版)》题目集 习题4-4 特殊a串数列求和