PHP8.1 Fiber交叉执行多任务(附代码详解)

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

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

$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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

1

1

2

2

3

3

4

4

5

5

6

6

7

7

8

8

9

9

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

$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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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

通过消息通知完成

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

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;

}

以上就是PHP8.1 Fiber交叉执行多任务(附代码详解)的详细内容,更多请关注php中文网其它相关文章!

原文链接:

https://www.php.cn/topic/php8/486174.html

学校电脑室专用操作系统GHOST WIN10 64位 纯净无广告无后门

提供了三种系统恢复工具
其中Ghost安装器 和 CGI硬盘安装增强版 支持mbr分区系统恢复
一键安装系统(支持GTP) 支持GTP EFI系统恢复

注意:系统恢复工具在恢复系统时会修改系统必要启动项,可能会被部分杀毒软件误报!

所以运行装机软件前一定要关闭所有杀毒软件或卫士!!!

请放心使用!

(本系统下载及其他软件,均基于自由分享为目的,请下载者测试完成后24小时内删除。)

本GHOST内集成了电子教室客户端,冰点还原,360企业版(无广告),WPS2019(无广告),火狐、谷歌,金山打字通(无广告)。
默认密码均为abc123

多台机器安装时请临时解锁冰点,然后修改成想要的主机名,再重启。

2022.3.11

系统下载地址:

链接1:https://pan.baidu.com/s/1DEC1WuF20wYDt-G0sxfMYw?pwd=wvi2
提取码:wvi2
–来自百度网盘超级会员V6的分享

链接2:https://pan.baidu.com/s/1CtcRTSHhYL9K6kUzD9yuxA?pwd=4321
提取码:4321
–来自百度网盘超级会员V6的分享

公共DNS集 和 IPV6 DNS

百度公共DNS 180.76.76.76

腾讯公共DNS:119.29.29.29

阿里云公共DNS 223.5.5.5

谷歌公共DNS 8.8.8.8(国内最慢的)

中国互联网络中心公共DNS 1.2.4.8

openDNS:208.67.222.222

公共IPV6 dns大全

一、阿里ipv6 dns

阿里的dns好在于自家的服务器遍布全球,加上自家研究的CDN技术快稳定,强大的阿里云团队技术坚持也是国内首家支持IPv4和IPv6,双端加持,安全快速。

2400:3200::1
2400:3200:baba::1

二、百度ipv6 dns

百度作为国内最大的搜索引擎服务商,也不甘示弱的推出了ipv6服务,成为国内第二个支持双端IPv4和IPv6服务商之一。

2400:da00::6666

三、天地互连 ipv6 dns

该服务是北京天地互连信息技术有限公司,官方没有太多的介绍,但在全球也布属了多台服务器,该公司响应工信部发文,率先推出国内首个ipv6dns服务。可以说该ipv6是国内最安全的dns之一,毕竟是国家项目。

240C::6666
240C::6644

四、谷歌 vip6 dns

作为全球最大的互联网公司之一的谷歌,也推出了ipv6dns服务,但对于国内用户来说,基本用不着,谷歌除广告业务外,其他业务基本都撤离了中国大陆,包括很多服务器,所有如果不是在香港、台湾一带或离国外交接的地方,不建议是要谷歌dns,服务器响应可能过慢。

2001:4860:4860::8888
2001:4860:4860::8844

目前互联网上能收集的大公司ipv6 dns也就这几家,其他的都是什么研究院和大学的,这就不做分类了,排名不分先后。

建议大家选用哪个DNS之前,可以用ping来测试一下,不同地区不同公司的时延不一样,可以选择延时最少的。

ping -6 IPV6地址

可以测试IPV6 DNS的响应速度。