您的当前位置:首页>全部文章>文章详情

【PHP】PHP8.1 Fiber交叉执行多任务

CrazyPanda发表于:2024-01-06 22:26:24浏览:321次TAG:


大家的电脑应该都是大等于2核的了,但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行,微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。(本文给大家抛个砖,欢迎大家补充更有意思的使用)


拿平时大家写的 for 循环举例。像 go 你可以写两个 go 每个里面各写一个循环同时输入,你可以看到输出是交替。在过去的php版本中,如果只开启一个 cli 写多个 for 循环,那么他的输出一定是顺序的。无法做到交叉输出(也就是无法在第一个循环中执行若干次后,让b再执行,b执行一段时间后,再让A执行)。

现在借助 fiber 我们也可以实现这种操作。【推荐学习:PHP视频教程

下面这段代码就可以做到两个循环交叉执行。甚至可以控制两个程序执行的频率(比如A执行3次,B执行一次这样分配)


<?php
$t1    = false;
$t2    = false;
$reg   = [];
$reg[] = new \Fiber(function () use (&$t1) {
    for ($i = 1; $i < 10; $i++) {
        echo $i;
        echo PHP_EOL;
        \Fiber::suspend();
 
    }
    $t1 = true;
});
 
 
$reg[] = new \Fiber(function () use (&$t2) {
    for ($i = 1; $i < 10; $i++) {
        echo $i;
        echo PHP_EOL;
        \Fiber::suspend();
    }
    $t2 = true;
});
 
$startTag = true;
while (count($reg) > 1) {
 
    if ($startTag) foreach ($reg as $pI) {
        $pI->start();
        $startTag = false;
    }
 
    foreach ($reg as $pI) {
        $pI->resume();
    }
 
    if ($t1 === true && $t2 === true) {
        break;
    }
}
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9

你甚至可以控制两个循环的执行频率,比如 第一个循环 执行3次后,第二个循环执行一次。代码如下

<?php
$reg = [];
$fId = 1;
 
 
$reg[$fId] = new \Fiber(function () use (&$reg, $fId) {
    for ($i = 1; $i < 10; $i++) {
        echo $fId . ':' . $i;
        echo PHP_EOL;
        if ($i % 3 == 0) {
            \Fiber::suspend();
        }
    }
    unset($reg[$fId]);
});
$fId++;
 
$reg[$fId] = new \Fiber(function () use (&$reg, $fId) {
    for ($i = 1; $i < 10; $i++) {
        echo $fId . ':' . $i;
        echo PHP_EOL;
        \Fiber::suspend();
    }
    unset($reg[$fId]);
});
 
$startTag = true;
while (count($reg) > 0) {
    if ($startTag) foreach ($reg as $pI) {
        $pI->start();
        $startTag = false;
    }
    foreach ($reg as $pI) {
        $pI->resume();
    }
}
1:1
1:2
1:3
2:1
1:4
1:5
1:6
2:2
1:7
1:8
1:9
2:3
2:4
2:5
2:6
2:7
2:8
2:9

通过消息通知完成

<?php
 
namespace App\Command;
 
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
 
#[AsCommand(
    name: 'Sname',
    description: 'Add a short description for your command',
)]
class SnameCommand extends Command
{
    protected function configure(): void
    {
        $this
            ->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
            ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description');
    }
 
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $t1  = false;
        $t2  = false;
        $reg = [];
        $fId = 1;
 
 
        $reg[] = new \Fiber(function () use ($fId) {
            for ($i = 1; $i < 10; $i++) {
                echo $fId . ':' . $i;
                echo PHP_EOL;
                if ($i % 3 == 0) {
                    \Fiber::suspend(new SuspendData(Status::Running));
                }
            }
            \Fiber::suspend(new SuspendData(Status::Stop));
 
        });
        $fId++;
 
        $reg[] = new \Fiber(function () use ($fId) {
            for ($i = 1; $i < 10; $i++) {
                echo $fId . ':' . $i;
                echo PHP_EOL;
                \Fiber::suspend(new SuspendData(Status::Running));
            }
            \Fiber::suspend(new SuspendData(Status::Stop));
        });
 
        $startTag = true;
        while (count($reg) > 0) {
            if ($startTag) foreach ($reg as $pI) {
                $pI->start();
                $startTag = false;
            }
            foreach ($reg as $key => $pI) {
                $r = $pI->resume();
                if ($r->status === Status::Stop) {
                  unset($reg[$key]);
                }
            }
        }
 
 
        return Command::SUCCESS;
    }
}
 
class SuspendData
{
    public readonly Status $status;
 
    public function __construct($status)
    {
        $this->status = $status;
    }
}
 
enum Status
{
    case Stop;
    case Running;
}


猜你喜欢

【PHP】Permission denied怎么解决
Permission denied的解决方法:1、确保当前用户具有足够的权限来执行该操作;2、如果当前用户没有足够的权限,可以尝试更改文件或目录的权限;3、如果当前用户不是管理员或没有足够的权限,可以尝试使用管理员权限来执行操作;4、可以尝试更改文件系统属性,以便允许写入操作;5、可以尝试释放磁盘空间,以便有足够的空间来执行操作;6、检查文件是否被其他进程占用。当我们遇到Permission denied这样的错误提示时,这通常意味着我们没有足够的权限来执行某个操作。解决Permiss
发表于:2023-12-06 浏览:368 TAG:
【PHP】thinkphp利用缓存提高数据库查询性能
ThinkPHP是一款十分受欢迎的PHP框架,它提供了许多便捷的功能和优化的设计,使得开发者可以更高效地进行Web应用程序的开发。其中,利用缓存提高数据库查询性能是一个常见的优化手段。本文将分享一些关于如何在ThinkPHP中利用缓存提高数据库查询性能的经验。一、什么是缓存?缓存是指将经常查询的数据存储在快速访问的存储介质中,以提高数据的访问速度。在Web应用程序中,数据库是最常用的数据存储介质之一。而经常查询数据库会带来一定的性能压力。因此,利用缓存可以避免频繁地查询数据库,从而提高
发表于:2023-12-08 浏览:430 TAG:
【PHP】关于bug率计算和它的实际意义
问题1:bug率有什么作用?my opion:用处有很多,需要具体情况具体分析,不过主要作用一般是来评价工作产品的质量。如果bug率较高,说明系统质量较差,需要大量的返工。项目经理就需要做好缺陷分析(缺陷的类型、分布、严重程度等),找出原因,以便做好下一阶段的缺陷预防工作。除此之外,还可以结合其它方面的信息,判断是否一些工作不充分。譬如,如果缺陷密度过低,有两个原因:可能工作产品质量确实高;也可能评审或测试不充分,更多的缺陷没有发现。在某些公司,bug率也作为项目度量考核的一项指标。问题2:bu
发表于:2024-06-22 浏览:260 TAG:
【PHP】Your requirements could not be resolved to an installable set of packages.
执行composer&nbsp;install遇到错误:Your requirements could not be resolved to an installable set of packages. 这是因为不匹配composer.json要求的版本,错误代码如下。Your&nbsp;requirements&nbsp;could&nbsp;not&nbsp;be&nbsp;resolved&nbsp;to&nbsp;an&nbsp;installable&nbsp;set&nbsp;of
发表于:2024-02-08 浏览:321 TAG:
【PHP】ThinkPHP如何防止SQL注入攻击
在ThinkPHP中,参数绑定是一种安全的方式,用于处理用户输入,特别是在构建数据库查询时。参数绑定可以防止SQL注入攻击,因为绑定的参数会被自动转义,而不是直接插入到SQL语句中。以下是在ThinkPHP中使用参数绑定的一些建议。1. 控制器中的参数绑定:在控制器中,可以使用bind方法进行参数绑定。以下是一个简单的示例:public&nbsp;function&nbsp;index($id) { &nbsp;&nbsp;&nbsp;&nbsp;$result&nbsp;=&nbsp;Db::
发表于:2024-01-04 浏览:336 TAG:
【PHP】PHP 框架中大型项目代码维护挑战与解决方法
在大型 php 项目中,代码维护面临主要挑战,包括依赖管理、代码重构、代码风格和文档。解决方法包括:使用依赖项管理器管理版本冲突。使用unittest框架在重构时保持代码完整性。建立并强制执行代码风格指南。建立文档策略并使用phpdoc生成文档。PHP 框架中大型项目代码维护挑战与解决方法在大型 PHP 项目中,代码维护可能是一个艰巨的任务。随着项目规模的增长,代码库会变得庞大且复杂,从而难以管理和更新。以下是 PHP 框架中代码维护面临的主要挑战以及解决这些挑战的一些方法:挑战 1:依赖管理依
发表于:2024-05-30 浏览:280 TAG:
【PHP】7个php字符串处理函数有哪些
7个php字符串处理函数有strlen()、strpos()、substr()、str_replace()、strtolower()、strtoupper()、trim()等。详细介绍:1、strlen(),用于获取字符串的长度;2、strpos(),用于查找字符串中的特定子串,返回第一次出现位置;3、substr(),用于获取字符串的子串;4、str_replace()等等。本教程操作系统:Windows10系统、PHP8.1.3版本、Dell G3电脑。在PHP中,有许多可以用于字
发表于:2023-12-04 浏览:694 TAG:
【PHP】CI,ThinkPHP,YII,Laravel框架比较
用过其中的yii TP CI框架。大概整理了这些框架的优点和缺点,有些错误的地方还希望大家指正。各个框架各有所长,针对的应用场景不同。一、Ci框架推崇简单就是美这一原则,没有花哨的设计模式,没有华丽的对象结构,一切就是那么简单。优点:框架的入门槛很低,极易学,极易用,框架很小,静态化非常容易配置简单,全部的配置使用php脚本来配置,执行效率高缺点:架构略简单,只能满足小型应用,略微不太能够满足中型应用需要大型项目扩展能力差,有些功能需要自己写扩展数据库类的扩展 ci给用户提供了一个名为call_
发表于:2024-07-14 浏览:313 TAG: #php #框架
【PHP】PHP防止SQL注入的方法
在开发php网站时,经常需要和数据库交互来存储和获取数据,然而,如果不对用户输入的数据进行处理,就可能会导致SQL注入攻击,SQL注入是一种常见的安全漏洞,攻击者可以通过恶意构造的输入数据来进入到数据库中,从而获取或篡改数据的行为+1.使用参数化查询2.输入验证和过滤filter_var 函数过滤用户输入的数据htmlspecialchars() 转换为HTML实
发表于:2024-07-14 浏览:266 TAG:
【PHP】PHP静态方法的优缺点
在PHP中,静态方法是一种特殊类型的方法,它不需要实例化类的对象就可以直接通过类名调用。静态方法通常用于那些不需要访问对象状态的场景,例如工具类、配置类或工厂模式等。下面将详细讨论静态方法的优缺点。
发表于:2025-04-17 浏览:28 TAG: #php