
<!DOCTYPE html>
<html lang="zh" data-goose-resource data-theme="gf-light">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="color-scheme" content="light dark">
    <meta name="theme-color" content="#fbfdff" data-goose-theme-color>
    <title>php[027]fiber - GooseForum</title>
    <meta name="description" content="大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...">
    <link rel="canonical" href="https://gooseforum.online/p/post/334">
    
    
    
    
    <meta property="og:title" content="php[027]fiber">
    <meta property="og:description" content="大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...">
    <meta property="og:type" content="article">
    <meta property="og:url" content="https://gooseforum.online/p/post/334">
    <meta property="og:site_name" content="GooseForum">
    
    <meta property="article:published_time" content="2022-09-05T20:40:00&#43;08:00">
    <meta property="article:modified_time" content="2025-12-30T20:46:43&#43;08:00">
    <meta property="article:author" content="abandon1a2b">
    <meta property="article:section" content="Coding">
    <meta property="article:tag" content="Coding">
    
    
    <meta name="twitter:card" content="summary">
    <meta name="twitter:title" content="php[027]fiber">
    <meta name="twitter:description" content="大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...">
    
    
    <script type="application/ld+json" data-goose-jsonld="page">{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"php[027]fiber","description":"大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...","text":"大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...","author":{"@type":"Person","name":"abandon1a2b","url":"https://gooseforum.online/u/1"},"publisher":{"@type":"Organization","name":"GooseForum","url":"https://gooseforum.online"},"datePublished":"2022-09-05T20:40:00+08:00","dateModified":"2025-12-30T20:46:43+08:00","url":"https://gooseforum.online/p/post/334","mainEntityOfPage":"https://gooseforum.online/p/post/334","articleSection":"Coding","keywords":["Coding"],"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":0},{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":594}]}</script>
    <link rel="icon" href="/static/pic/icon.webp">
    <script defer src="https://umami.leancodebox.online/script.js" data-website-id="0a633415-dd84-4264-98cd-a006e6a8fefc" data-performance="true"></script>
    <link rel="stylesheet" href="/assets/assets/site-Dalf7QD1.css" crossorigin>
<script type="module" src="/assets/assets/site-DZYE0hG5.js" crossorigin></script>

    <link id="goose-site-theme-link" rel="stylesheet" href="/site-theme.css?v=3535d0c163954d2c">
</head>
<body class="bg-base-200 text-base-content antialiased">
    <script id="goose-payload" type="application/json">{"component":"topic.detail","props":{"topic":{"id":334,"title":"php[027]fiber","description":"大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...","url":"/p/post/334","topicStatus":1,"processStatus":0,"author":{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp","wornBadge":{"code":"king","type":"system","grantMode":"manual","name":"King","description":"社区之王","iconType":"asset","iconKey":"","iconUrl":"/static/badges/king.svg","color":"amber","level":"special","isEnabled":true,"isWearable":true,"sortOrder":1,"source":"manual","reason":"管理员手动授予","grantedAt":"2026-06-07 18:52:33"}},"participants":[{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp","wornBadge":{"code":"king","type":"system","grantMode":"manual","name":"King","description":"社区之王","iconType":"asset","iconKey":"","iconUrl":"/static/badges/king.svg","color":"amber","level":"special","isEnabled":true,"isWearable":true,"sortOrder":1,"source":"manual","reason":"管理员手动授予","grantedAt":"2026-06-07 18:52:33"}}],"categories":[{"id":4,"name":"Coding","url":"/c/Coding/4","color":"#8241d6"}],"replyCount":0,"maxPostNo":1,"viewCount":594,"likeCount":0,"isLiked":false,"isBookmarked":false,"isWatched":false,"createdAt":"2022-09-05 20:40:00","updatedAt":"2025-12-30 20:46:43"},"postStream":{"posts":[{"id":151,"topicId":334,"postNo":1,"content":"\n\u003e 大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。\n\n拿平时大家写的 for 循环举例。像 go 你可以写两个 `go` 每个里面各写一个循环同时输入，你可以看到输出是交替。在过去的php版本中，如果只开启一个 cli 写多个 for 循环，那么他的输出一定是顺序的。无法做到交叉输出（也就是无法在第一个循环中执行若干次后，让b再执行，b执行一段时间后，再让A执行）。现在借助 fiber 我们也可以实现这种操作。下面这段代码就可以做到两个循环交叉执行。甚至可以控制两个程序执行的频率（比如A执行3次，B执行一次这样分配）\n\n\u003c!--more--\u003e\n\n\n```php\n\u003c?php\n$t1    = false;\n$t2    = false;\n$reg   = [];\n$reg[] = new \\Fiber(function () use (\u0026$t1) {\n    for ($i = 1; $i \u003c 10; $i++) {\n        echo $i;\n        echo PHP_EOL;\n        \\Fiber::suspend();\n\n    }\n    $t1 = true;\n});\n\n\n$reg[] = new \\Fiber(function () use (\u0026$t2) {\n    for ($i = 1; $i \u003c 10; $i++) {\n        echo $i;\n        echo PHP_EOL;\n        \\Fiber::suspend();\n    }\n    $t2 = true;\n});\n\n$startTag = true;\nwhile (count($reg) \u003e 1) {\n\n    if ($startTag) foreach ($reg as $pI) {\n        $pI-\u003estart();\n        $startTag = false;\n    }\n\n    foreach ($reg as $pI) {\n        $pI-\u003eresume();\n    }\n\n    if ($t1 === true \u0026\u0026 $t2 === true) {\n        break;\n    }\n}\n```\n```\n1\n1\n2\n2\n3\n3\n4\n4\n5\n5\n6\n6\n7\n7\n8\n8\n9\n9\n```\n\n你甚至可以控制两个循环的执行频率，比如 第一个循环 执行3次后，第二个循环执行一次。代码如下\n\n\n```php\n\u003c?php\n$reg = [];\n$fId = 1;\n\n\n$reg[$fId] = new \\Fiber(function () use (\u0026$reg, $fId) {\n    for ($i = 1; $i \u003c 10; $i++) {\n        echo $fId . ':' . $i;\n        echo PHP_EOL;\n        if ($i % 3 == 0) {\n            \\Fiber::suspend();\n        }\n    }\n    unset($reg[$fId]);\n});\n$fId++;\n\n$reg[$fId] = new \\Fiber(function () use (\u0026$reg, $fId) {\n    for ($i = 1; $i \u003c 10; $i++) {\n        echo $fId . ':' . $i;\n        echo PHP_EOL;\n        \\Fiber::suspend();\n    }\n    unset($reg[$fId]);\n});\n\n$startTag = true;\nwhile (count($reg) \u003e 0) {\n    if ($startTag) foreach ($reg as $pI) {\n        $pI-\u003estart();\n        $startTag = false;\n    }\n    foreach ($reg as $pI) {\n        $pI-\u003eresume();\n    }\n}\n\n```\n\n```\n1:1\n1:2\n1:3\n2:1\n1:4\n1:5\n1:6\n2:2\n1:7\n1:8\n1:9\n2:3\n2:4\n2:5\n2:6\n2:7\n2:8\n2:9\n```\n通过消息通知完成\n\n```php\n\u003c?php\n\nnamespace App\\Command;\n\nuse Symfony\\Component\\Console\\Attribute\\AsCommand;\nuse Symfony\\Component\\Console\\Command\\Command;\nuse Symfony\\Component\\Console\\Input\\InputArgument;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\n\n#[AsCommand(\n    name: 'Sname',\n    description: 'Add a short description for your command',\n)]\nclass SnameCommand extends Command\n{\n    protected function configure(): void\n    {\n        $this\n            -\u003eaddArgument('arg1', InputArgument::OPTIONAL, 'Argument description')\n            -\u003eaddOption('option1', null, InputOption::VALUE_NONE, 'Option description');\n    }\n\n    protected function execute(InputInterface $input, OutputInterface $output): int\n    {\n        $t1  = false;\n        $t2  = false;\n        $reg = [];\n        $fId = 1;\n\n\n        $reg[] = new \\Fiber(function () use ($fId) {\n            for ($i = 1; $i \u003c 10; $i++) {\n                echo $fId . ':' . $i;\n                echo PHP_EOL;\n                if ($i % 3 == 0) {\n                    \\Fiber::suspend(new SuspendData(Status::Running));\n                }\n            }\n            \\Fiber::suspend(new SuspendData(Status::Stop));\n\n        });\n        $fId++;\n\n        $reg[] = new \\Fiber(function () use ($fId) {\n            for ($i = 1; $i \u003c 10; $i++) {\n                echo $fId . ':' . $i;\n                echo PHP_EOL;\n                \\Fiber::suspend(new SuspendData(Status::Running));\n            }\n            \\Fiber::suspend(new SuspendData(Status::Stop));\n        });\n\n        $startTag = true;\n        while (count($reg) \u003e 0) {\n            if ($startTag) foreach ($reg as $pI) {\n                $pI-\u003estart();\n                $startTag = false;\n            }\n            foreach ($reg as $key =\u003e $pI) {\n                $r = $pI-\u003eresume();\n                if ($r-\u003estatus === Status::Stop) {\n                  unset($reg[$key]);\n                }\n            }\n        }\n\n\n        return Command::SUCCESS;\n    }\n}\n\nclass SuspendData\n{\n    public readonly Status $status;\n\n    public function __construct($status)\n    {\n        $this-\u003estatus = $status;\n    }\n}\n\nenum Status\n{\n    case Stop;\n    case Running;\n}\n```\n\n欢迎大家补充\n","renderedContent":"\u003cblockquote\u003e\n\u003cp\u003e大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e拿平时大家写的 for 循环举例。像 go 你可以写两个 \u003ccode\u003ego\u003c/code\u003e 每个里面各写一个循环同时输入，你可以看到输出是交替。在过去的php版本中，如果只开启一个 cli 写多个 for 循环，那么他的输出一定是顺序的。无法做到交叉输出（也就是无法在第一个循环中执行若干次后，让b再执行，b执行一段时间后，再让A执行）。现在借助 fiber 我们也可以实现这种操作。下面这段代码就可以做到两个循环交叉执行。甚至可以控制两个程序执行的频率（比如A执行3次，B执行一次这样分配）\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cpre\u003e\u003ccode class=\"language-php\"\u003e\u0026lt;?php\n$t1    = false;\n$t2    = false;\n$reg   = [];\n$reg[] = new \\Fiber(function () use (\u0026amp;$t1) {\n    for ($i = 1; $i \u0026lt; 10; $i++) {\n        echo $i;\n        echo PHP_EOL;\n        \\Fiber::suspend();\n\n    }\n    $t1 = true;\n});\n\n\n$reg[] = new \\Fiber(function () use (\u0026amp;$t2) {\n    for ($i = 1; $i \u0026lt; 10; $i++) {\n        echo $i;\n        echo PHP_EOL;\n        \\Fiber::suspend();\n    }\n    $t2 = true;\n});\n\n$startTag = true;\nwhile (count($reg) \u0026gt; 1) {\n\n    if ($startTag) foreach ($reg as $pI) {\n        $pI-\u0026gt;start();\n        $startTag = false;\n    }\n\n    foreach ($reg as $pI) {\n        $pI-\u0026gt;resume();\n    }\n\n    if ($t1 === true \u0026amp;\u0026amp; $t2 === true) {\n        break;\n    }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cpre\u003e\u003ccode\u003e1\n1\n2\n2\n3\n3\n4\n4\n5\n5\n6\n6\n7\n7\n8\n8\n9\n9\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e你甚至可以控制两个循环的执行频率，比如 第一个循环 执行3次后，第二个循环执行一次。代码如下\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-php\"\u003e\u0026lt;?php\n$reg = [];\n$fId = 1;\n\n\n$reg[$fId] = new \\Fiber(function () use (\u0026amp;$reg, $fId) {\n    for ($i = 1; $i \u0026lt; 10; $i++) {\n        echo $fId . \u0026#39;:\u0026#39; . $i;\n        echo PHP_EOL;\n        if ($i % 3 == 0) {\n            \\Fiber::suspend();\n        }\n    }\n    unset($reg[$fId]);\n});\n$fId++;\n\n$reg[$fId] = new \\Fiber(function () use (\u0026amp;$reg, $fId) {\n    for ($i = 1; $i \u0026lt; 10; $i++) {\n        echo $fId . \u0026#39;:\u0026#39; . $i;\n        echo PHP_EOL;\n        \\Fiber::suspend();\n    }\n    unset($reg[$fId]);\n});\n\n$startTag = true;\nwhile (count($reg) \u0026gt; 0) {\n    if ($startTag) foreach ($reg as $pI) {\n        $pI-\u0026gt;start();\n        $startTag = false;\n    }\n    foreach ($reg as $pI) {\n        $pI-\u0026gt;resume();\n    }\n}\n\n\u003c/code\u003e\u003c/pre\u003e\n\u003cpre\u003e\u003ccode\u003e1:1\n1:2\n1:3\n2:1\n1:4\n1:5\n1:6\n2:2\n1:7\n1:8\n1:9\n2:3\n2:4\n2:5\n2:6\n2:7\n2:8\n2:9\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e通过消息通知完成\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-php\"\u003e\u0026lt;?php\n\nnamespace App\\Command;\n\nuse Symfony\\Component\\Console\\Attribute\\AsCommand;\nuse Symfony\\Component\\Console\\Command\\Command;\nuse Symfony\\Component\\Console\\Input\\InputArgument;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Style\\SymfonyStyle;\n\n#[AsCommand(\n    name: \u0026#39;Sname\u0026#39;,\n    description: \u0026#39;Add a short description for your command\u0026#39;,\n)]\nclass SnameCommand extends Command\n{\n    protected function configure(): void\n    {\n        $this\n            -\u0026gt;addArgument(\u0026#39;arg1\u0026#39;, InputArgument::OPTIONAL, \u0026#39;Argument description\u0026#39;)\n            -\u0026gt;addOption(\u0026#39;option1\u0026#39;, null, InputOption::VALUE_NONE, \u0026#39;Option description\u0026#39;);\n    }\n\n    protected function execute(InputInterface $input, OutputInterface $output): int\n    {\n        $t1  = false;\n        $t2  = false;\n        $reg = [];\n        $fId = 1;\n\n\n        $reg[] = new \\Fiber(function () use ($fId) {\n            for ($i = 1; $i \u0026lt; 10; $i++) {\n                echo $fId . \u0026#39;:\u0026#39; . $i;\n                echo PHP_EOL;\n                if ($i % 3 == 0) {\n                    \\Fiber::suspend(new SuspendData(Status::Running));\n                }\n            }\n            \\Fiber::suspend(new SuspendData(Status::Stop));\n\n        });\n        $fId++;\n\n        $reg[] = new \\Fiber(function () use ($fId) {\n            for ($i = 1; $i \u0026lt; 10; $i++) {\n                echo $fId . \u0026#39;:\u0026#39; . $i;\n                echo PHP_EOL;\n                \\Fiber::suspend(new SuspendData(Status::Running));\n            }\n            \\Fiber::suspend(new SuspendData(Status::Stop));\n        });\n\n        $startTag = true;\n        while (count($reg) \u0026gt; 0) {\n            if ($startTag) foreach ($reg as $pI) {\n                $pI-\u0026gt;start();\n                $startTag = false;\n            }\n            foreach ($reg as $key =\u0026gt; $pI) {\n                $r = $pI-\u0026gt;resume();\n                if ($r-\u0026gt;status === Status::Stop) {\n                  unset($reg[$key]);\n                }\n            }\n        }\n\n\n        return Command::SUCCESS;\n    }\n}\n\nclass SuspendData\n{\n    public readonly Status $status;\n\n    public function __construct($status)\n    {\n        $this-\u0026gt;status = $status;\n    }\n}\n\nenum Status\n{\n    case Stop;\n    case Running;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e欢迎大家补充\u003c/p\u003e\n","processStatus":0,"isHidden":false,"canModerate":false,"author":{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp","wornBadge":{"code":"king","type":"system","grantMode":"manual","name":"King","description":"社区之王","iconType":"asset","iconKey":"","iconUrl":"/static/badges/king.svg","color":"amber","level":"special","isEnabled":true,"isWearable":true,"sortOrder":1,"source":"manual","reason":"管理员手动授予","grantedAt":"2026-06-07 18:52:33"}},"createdAt":"2022-09-05 20:40:00","isOwnPost":false,"updatedAt":"2025-12-30 20:46:43"}],"replyTargets":[],"beforePostNo":1,"afterPostNo":1,"hasBefore":false,"hasAfter":false,"total":1,"maxPostNo":1},"hotTopics":[{"id":432,"title":"一些建议和bug","description":"Footer 中的 Primary 类使用 Html，无法编译 url 和 a 标签，会显示纯 Html 代码 下方文字内容 （Primary）\"，还是会出现原html， Power by \u003ca href=\"https://github.com/leancodebox/GooseForum\"\u003eGooseForum\u003c/a\u003e. “外部资源链接 / Meta 标签” 若为空，则会导致无法保存，500错误...","url":"/p/post/432","pinWeight":0,"processStatus":0,"author":{"id":28,"username":"yannis","avatarUrl":"/file/img/avatars/avatar_28_1779205979/ebd0888e-11d4-439f-8a99-fc5de7bd00eb.webp"},"participants":[{"id":28,"username":"yannis","avatarUrl":"/file/img/avatars/avatar_28_1779205979/ebd0888e-11d4-439f-8a99-fc5de7bd00eb.webp"},{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp"},{"id":31,"username":"mopwang","avatarUrl":"/static/pic/5.webp"}],"categories":[{"id":8,"name":"吐槽/脑洞","url":"/c/happy/8","color":"#5d41d6"}],"replyCount":52,"viewCount":828,"activityText":"2026-07-08 20:25:00","lastUpdateTime":"2026-07-08 20:25:00"},{"id":484,"title":"「许愿池」后续功能讨论","description":"第一阶段，大家有什么想法吗分组或者圈子以及对应权限这个功能有什么想法吗。 这边关于分组的配置可能得走 EXISTS 控制了。主要是GooseForum目前仍打算保持多分类这个能力。 一般来说，一个主题或者文章会绑定一个分类，但是实际情况是，如果一个文章，例如一个关于物理问题的数学公式，那么这个文章天然应该分别出现在物理/数学两个分类里面，就目前为止确实看到不少论坛因为限制了单类型，导致用户针对同一...","url":"/p/post/484","pinWeight":10,"processStatus":0,"author":{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp"},"participants":[{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp"},{"id":51,"username":"weilaimeng","avatarUrl":"/static/pic/8.webp"},{"id":72,"username":"xqbncom","avatarUrl":"/static/pic/8.webp"}],"categories":[{"id":6,"name":"GooseForum","url":"/c/GooseForum/6","color":"#41d641"}],"replyCount":23,"viewCount":428,"activityText":"2026-08-05 10:28:04","lastUpdateTime":"2026-08-05 10:28:04"},{"id":481,"title":"后台可以自定义侧边栏文字功能，这样就可以适应很多场景","description":"首页侧边栏菜单可以自定义文字添加和排序，后台添加个菜单栏管理功能，更灵活，页面头部链接也能在后台自定义就很好使了","url":"/p/post/481","pinWeight":0,"processStatus":0,"author":{"id":59,"username":"xnkyns","avatarUrl":"/static/pic/12.webp"},"participants":[{"id":59,"username":"xnkyns","avatarUrl":"/static/pic/12.webp"},{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp"}],"categories":[{"id":8,"name":"吐槽/脑洞","url":"/c/happy/8","color":"#5d41d6"}],"replyCount":18,"viewCount":349,"activityText":"2026-07-17 15:13:51","lastUpdateTime":"2026-07-17 15:13:51"},{"id":467,"title":"震惊！！点进标题帖子，返回键会回到顶部？？","description":"顶部往下刷到底点进标题帖子，返回键会回到顶部，没有返回到刚刚点进标题帖子的停留！每次返回还得往下刷找找刚刚点进的帖子😅","url":"/p/post/467","pinWeight":0,"processStatus":0,"author":{"id":51,"username":"weilaimeng","avatarUrl":"/static/pic/8.webp"},"participants":[{"id":51,"username":"weilaimeng","avatarUrl":"/static/pic/8.webp"},{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp"},{"id":31,"username":"mopwang","avatarUrl":"/static/pic/5.webp"}],"categories":[{"id":8,"name":"吐槽/脑洞","url":"/c/happy/8","color":"#5d41d6"}],"replyCount":18,"viewCount":282,"activityText":"2026-07-08 20:25:00","lastUpdateTime":"2026-07-08 20:25:00"},{"id":479,"title":"[已回迁]服务器迁移","description":"RT 基本迁移完毕。看看效果先","url":"/p/post/479","pinWeight":0,"processStatus":0,"author":{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp"},"participants":[{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp"},{"id":31,"username":"mopwang","avatarUrl":"/static/pic/5.webp"},{"id":51,"username":"weilaimeng","avatarUrl":"/static/pic/8.webp"}],"categories":[{"id":6,"name":"GooseForum","url":"/c/GooseForum/6","color":"#41d641"}],"replyCount":13,"viewCount":267,"activityText":"2026-07-08 20:25:01","lastUpdateTime":"2026-07-08 20:25:01"},{"id":439,"title":"请问大佬怎么用宝塔部署此项目","description":"这个有没有宝塔的安装教程，看这个论坛系统不错，界面也好看，但是不会安装，因为doxker有其他的项目，这个不会安装，能不能出个宝塔安装的教程？。","url":"/p/post/439","pinWeight":0,"processStatus":0,"author":{"id":31,"username":"mopwang","avatarUrl":"/static/pic/5.webp"},"participants":[{"id":31,"username":"mopwang","avatarUrl":"/static/pic/5.webp"},{"id":1,"username":"abandon1a2b","avatarUrl":"/file/img/avatars/1/1779889413613587649/avatar.webp"}],"categories":[{"id":6,"name":"GooseForum","url":"/c/GooseForum/6","color":"#41d641"}],"replyCount":13,"viewCount":313,"activityText":"2026-07-08 20:25:00","lastUpdateTime":"2026-07-08 20:25:00"}],"permissions":{"isOwnTopic":false,"canPost":false,"canModerateTopic":false}},"meta":{"title":"php[027]fiber - GooseForum","description":"大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...","canonical":"https://gooseforum.online/p/post/334","openGraph":{"title":"php[027]fiber","description":"大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...","type":"article","url":"https://gooseforum.online/p/post/334","siteName":"GooseForum","publishedTime":"2022-09-05T20:40:00+08:00","modifiedTime":"2025-12-30T20:46:43+08:00","author":"abandon1a2b","section":"Coding","tags":["Coding"]},"twitter":{"card":"summary","title":"php[027]fiber","description":"大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的..."},"jsonLd":{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"php[027]fiber","description":"大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...","text":"大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...","author":{"@type":"Person","name":"abandon1a2b","url":"https://gooseforum.online/u/1"},"publisher":{"@type":"Organization","name":"GooseForum","url":"https://gooseforum.online"},"datePublished":"2022-09-05T20:40:00+08:00","dateModified":"2025-12-30T20:46:43+08:00","url":"https://gooseforum.online/p/post/334","mainEntityOfPage":"https://gooseforum.online/p/post/334","articleSection":"Coding","keywords":["Coding"],"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":0},{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":594}]}},"layout":{"site":{"name":"GooseForum","description":"🦢 大鹅栖息地 | 自由漫谈的江湖茶馆","logo":"/static/pic/icon.webp","favicon":"/static/pic/icon.webp","externalLinks":"\u003cscript defer src=\"https://umami.leancodebox.online/script.js\" data-website-id=\"0a633415-dd84-4264-98cd-a006e6a8fefc\" data-performance=\"true\"\u003e\u003c/script\u003e","brandType":"default","brandText":"","brandImage":""},"viewer":{"id":0,"username":"","email":"","avatarUrl":"","isAuthenticated":false,"canAccessAdmin":false,"isModerator":false,"requiresEmailVerification":false,"adminPermissions":[]},"header":[{"key":"sponsors","label":"Sponsors","i18nLabel":"shell.nav.sponsors","url":"/sponsors"},{"key":"links","label":"Links","i18nLabel":"shell.nav.links","url":"/links"},{"key":"5cb54b55-2ea7-44f5-8a75-d39df8db56af","label":"烙铁双击666","url":"https://www.yuanshen.com/"}],"sidebar":{"categories":[{"id":4,"label":"Coding","url":"/c/Coding/4","color":"#8241d6"},{"id":8,"label":"吐槽/脑洞","url":"/c/happy/8","color":"#5d41d6"},{"id":10,"label":"HelpMe","url":"/c/HelpMe/10","color":"#41d644"},{"id":11,"label":"Game","url":"/c/Game/11","color":"#d66e41"},{"id":7,"label":"AI","url":"/c/AI/7","color":"#b941d6"},{"id":6,"label":"GooseForum","url":"/c/GooseForum/6","color":"#41d641"}],"activeKey":"category_4"},"footer":{"links":[{"name":"RSS","url":"/rss.xml"},{"name":"Site Map","url":"/sitemap.xml"},{"name":"GooseForum","url":"https://github.com/leancodebox/GooseForum"}],"primary":["GooseForum © 2024"]},"unread":{"notifications":false,"messages":false,"moderationReports":false},"theme":{"enabled":true,"href":"/site-theme.css?v=3535d0c163954d2c","colors":{"gf-dark":"#101418","gf-light":"#fbfdff"},"current":"gf-light","themeColor":"#fbfdff"}},"url":"https://gooseforum.online/p/post/334","version":"1.0"}</script>

    <div id="goose-app" aria-live="polite"></div>

    <noscript>
        <style data-goose-crawler-style>
            noscript main { max-width: 1180px; margin: 0 auto; padding: 32px 24px; color: #6b7280; font: 16px/1.6 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
            noscript h1 { margin: 0 0 28px; color: #111827; font-size: 28px; line-height: 1.25; }
            noscript a { color: #0284c7; text-decoration: underline; text-underline-offset: 2px; }
            noscript .gf-crawler-header { border-bottom: 1px solid #e5e7eb; }
            noscript .gf-crawler-header-inner { max-width: 1180px; margin: 0 auto; padding: 18px 24px; }
            noscript .gf-crawler-home-link { color: #0284c7; font-size: 18px; font-weight: 600; }
            noscript .gf-crawler-topic-list { width: 100%; }
            noscript .gf-crawler-topic-list-head, noscript .gf-crawler-topic-row { display: grid; grid-template-columns: minmax(0, 1fr) 120px 120px 160px; }
            noscript .gf-crawler-topic-list-head { border-bottom: 2px solid #e5e7eb; color: #9ca3af; font-size: 15px; font-weight: 600; }
            noscript .gf-crawler-topic-list-head span { padding: 0 12px 10px; }
            noscript .gf-crawler-topic-list-head span:not(:first-child) { text-align: center; white-space: nowrap; }
            noscript .gf-crawler-topic-items { margin: 0; padding: 0; list-style: none; }
            noscript .gf-crawler-topic-row { border-bottom: 1px solid #e5e7eb; }
            noscript .gf-crawler-topic-row > div { padding: 20px 12px; align-self: center; }
            noscript .gf-crawler-visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
            noscript .gf-crawler-topic-title { margin: 0 0 4px; font-size: 20px; line-height: 1.35; }
            noscript .gf-crawler-topic-meta { margin: 0 0 12px; color: #6b7280; font-size: 14px; }
            noscript .gf-crawler-topic-meta a { margin-right: 8px; }
            noscript .gf-crawler-topic-excerpt { max-width: 760px; margin: 0; color: #8b9098; }
            noscript .gf-crawler-topic-number, noscript .gf-crawler-topic-activity { color: #8b9098; text-align: center; white-space: nowrap; }
            noscript .gf-crawler-topic-page { max-width: 920px; }
            noscript .gf-crawler-topic-head { padding-bottom: 24px; border-bottom: 1px solid #e5e7eb; }
            noscript .gf-crawler-topic-summary { max-width: 760px; margin: -14px 0 18px; color: #8b9098; font-size: 17px; }
            noscript .gf-crawler-post-meta { margin: 0 0 18px; color: #8b9098; font-size: 14px; }
            noscript .gf-crawler-post-meta a, noscript .gf-crawler-post-meta span, noscript .gf-crawler-post-meta time { margin-right: 12px; }
            noscript .gf-crawler-post-body { max-width: 760px; color: #374151; }
            noscript .gf-crawler-post-body img, noscript .gf-crawler-post-body video { display: block; max-width: 100%; max-height: 560px; width: auto; height: auto; object-fit: contain; }
            noscript .gf-crawler-post-body figure { margin: 16px 0; max-width: 100%; }
            noscript .gf-crawler-post-body table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; }
            noscript .gf-crawler-post-body pre { overflow: auto; padding: 12px; background: #f3f4f6; }
            noscript .gf-crawler-post-list { margin-top: 28px; }
            noscript .gf-crawler-post-list h2 { margin: 0 0 8px; color: #111827; font-size: 20px; }
            noscript .gf-crawler-post-list ol { margin: 0; padding: 0; list-style: none; }
            noscript .gf-crawler-post { padding: 18px 0; border-top: 1px solid #e5e7eb; }
            noscript .gf-crawler-user-page { max-width: 980px; }
            noscript .gf-crawler-user-head { display: flex; gap: 18px; align-items: center; padding-bottom: 22px; border-bottom: 1px solid #e5e7eb; }
            noscript .gf-crawler-user-avatar { width: 88px; height: 88px; border-radius: 50%; object-fit: cover; background: #f3f4f6; }
            noscript .gf-crawler-user-head h1 { margin: 0 0 4px; }
            noscript .gf-crawler-user-meta, noscript .gf-crawler-user-bio { margin: 0; color: #8b9098; }
            noscript .gf-crawler-user-bio { margin-top: 10px; max-width: 680px; color: #6b7280; }
            noscript .gf-crawler-user-stats dl { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin: 20px 0 32px; }
            noscript .gf-crawler-user-stats div { padding: 12px 0; border-bottom: 1px solid #e5e7eb; }
            noscript .gf-crawler-user-stats dt { color: #8b9098; font-size: 13px; }
            noscript .gf-crawler-user-stats dd { margin: 2px 0 0; color: #374151; font-size: 20px; }
            noscript .gf-crawler-user-section { margin-top: 28px; }
            noscript .gf-crawler-user-section h2 { margin: 0 0 12px; color: #111827; font-size: 20px; }
            noscript .gf-crawler-activity-list { margin: 0; padding: 0; list-style: none; }
            noscript .gf-crawler-activity { padding: 14px 0; border-top: 1px solid #e5e7eb; }
            noscript .gf-crawler-activity time { display: block; margin-top: 4px; color: #8b9098; font-size: 14px; }
            noscript .gf-crawler-footer { max-width: 1180px; margin: 24px auto 0; padding: 20px 24px 32px; border-top: 1px solid #e5e7eb; color: #374151; }
            noscript .gf-crawler-footer p { margin: 0; }
            @media (max-width: 700px) {
                noscript main { padding: 24px 16px; }
                noscript .gf-crawler-header-inner, noscript .gf-crawler-footer { padding-left: 16px; padding-right: 16px; }
                noscript .gf-crawler-topic-list-head { display: none; }
                noscript .gf-crawler-topic-row { display: grid; grid-template-columns: 1fr; padding: 18px 0; }
                noscript .gf-crawler-topic-row > div { width: 100%; padding: 0; text-align: left; white-space: normal; }
                noscript .gf-crawler-topic-row > div:not(:first-child) { width: auto; margin-right: 12px; color: #8b9098; font-size: 14px; white-space: nowrap; }
                noscript .gf-crawler-topic-title { font-size: 18px; }
                noscript .gf-crawler-topic-excerpt { margin-top: 8px; }
                noscript .gf-crawler-user-head { align-items: flex-start; }
                noscript .gf-crawler-user-stats dl { grid-template-columns: repeat(2, minmax(0, 1fr)); }
            }
        </style>
        <header class="gf-crawler-header">
            <div class="gf-crawler-header-inner">
                <a class="gf-crawler-home-link" href="/">GooseForum</a>
            </div>
        </header>
        

<main class="gf-crawler-topic-page">
    <article class="gf-crawler-topic-head">
        <h1>php[027]fiber</h1>
        <p class="gf-crawler-topic-summary">大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。 拿平时大家写的...</p>
        <p class="gf-crawler-post-meta">
            
            
            <a href="/c/Coding/4" rel="tag">Coding</a>
            
            
            <a href="/u/1">abandon1a2b</a>
            <time datetime="2022-09-05T20:40:00&#43;08:00">2022-09-05 20:40:00</time>
            <time datetime="2025-12-30T20:46:43&#43;08:00">更新于 2025-12-30 20:46:43</time>
            <span>0 回复</span>
            <span>0 赞</span>
            <span>594 浏览</span>
        </p>
    </article>

    
    <section class="gf-crawler-post-list" aria-label="帖子">
        <h2>帖子</h2>
        <ol>
            
            <li id="post-151" class="gf-crawler-post">
                <article>
                    <p class="gf-crawler-post-meta">
                        <a href="#post-151">#1</a>
                        <a href="/u/1">abandon1a2b</a>
                        <time>2022-09-05 20:40:00</time>
                    </p>
                    
                    <div class="gf-crawler-post-body">
                    
                    <blockquote>
<p>大家的电脑应该都是大等于2核的了，但是大家电脑上同时运行的程序大多远远多于cpu的核心数量。这是因为操作系统在任务处理上采取了宏观上并行，微观上串行的做法。也就是cpu每个程序都执行了一点点时间然后就切换去执行别的程序。使得大家看上去都执行了很多。现在 php8.1 。推出了 fiber 。把调度权利赋予给了各位 php 开发。那么我们有 fiber 我们可以实现什么样的新操作呢。</p>
</blockquote>
<p>拿平时大家写的 for 循环举例。像 go 你可以写两个 <code>go</code> 每个里面各写一个循环同时输入，你可以看到输出是交替。在过去的php版本中，如果只开启一个 cli 写多个 for 循环，那么他的输出一定是顺序的。无法做到交叉输出（也就是无法在第一个循环中执行若干次后，让b再执行，b执行一段时间后，再让A执行）。现在借助 fiber 我们也可以实现这种操作。下面这段代码就可以做到两个循环交叉执行。甚至可以控制两个程序执行的频率（比如A执行3次，B执行一次这样分配）</p>
<!-- raw HTML omitted -->
<pre><code class="language-php">&lt;?php
$t1    = false;
$t2    = false;
$reg   = [];
$reg[] = new \Fiber(function () use (&amp;$t1) {
    for ($i = 1; $i &lt; 10; $i++) {
        echo $i;
        echo PHP_EOL;
        \Fiber::suspend();

    }
    $t1 = true;
});


$reg[] = new \Fiber(function () use (&amp;$t2) {
    for ($i = 1; $i &lt; 10; $i++) {
        echo $i;
        echo PHP_EOL;
        \Fiber::suspend();
    }
    $t2 = true;
});

$startTag = true;
while (count($reg) &gt; 1) {

    if ($startTag) foreach ($reg as $pI) {
        $pI-&gt;start();
        $startTag = false;
    }

    foreach ($reg as $pI) {
        $pI-&gt;resume();
    }

    if ($t1 === true &amp;&amp; $t2 === true) {
        break;
    }
}
</code></pre>
<pre><code>1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
</code></pre>
<p>你甚至可以控制两个循环的执行频率，比如 第一个循环 执行3次后，第二个循环执行一次。代码如下</p>
<pre><code class="language-php">&lt;?php
$reg = [];
$fId = 1;


$reg[$fId] = new \Fiber(function () use (&amp;$reg, $fId) {
    for ($i = 1; $i &lt; 10; $i++) {
        echo $fId . &#39;:&#39; . $i;
        echo PHP_EOL;
        if ($i % 3 == 0) {
            \Fiber::suspend();
        }
    }
    unset($reg[$fId]);
});
$fId++;

$reg[$fId] = new \Fiber(function () use (&amp;$reg, $fId) {
    for ($i = 1; $i &lt; 10; $i++) {
        echo $fId . &#39;:&#39; . $i;
        echo PHP_EOL;
        \Fiber::suspend();
    }
    unset($reg[$fId]);
});

$startTag = true;
while (count($reg) &gt; 0) {
    if ($startTag) foreach ($reg as $pI) {
        $pI-&gt;start();
        $startTag = false;
    }
    foreach ($reg as $pI) {
        $pI-&gt;resume();
    }
}

</code></pre>
<pre><code>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
</code></pre>
<p>通过消息通知完成</p>
<pre><code class="language-php">&lt;?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: &#39;Sname&#39;,
    description: &#39;Add a short description for your command&#39;,
)]
class SnameCommand extends Command
{
    protected function configure(): void
    {
        $this
            -&gt;addArgument(&#39;arg1&#39;, InputArgument::OPTIONAL, &#39;Argument description&#39;)
            -&gt;addOption(&#39;option1&#39;, null, InputOption::VALUE_NONE, &#39;Option description&#39;);
    }

    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 &lt; 10; $i++) {
                echo $fId . &#39;:&#39; . $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 &lt; 10; $i++) {
                echo $fId . &#39;:&#39; . $i;
                echo PHP_EOL;
                \Fiber::suspend(new SuspendData(Status::Running));
            }
            \Fiber::suspend(new SuspendData(Status::Stop));
        });

        $startTag = true;
        while (count($reg) &gt; 0) {
            if ($startTag) foreach ($reg as $pI) {
                $pI-&gt;start();
                $startTag = false;
            }
            foreach ($reg as $key =&gt; $pI) {
                $r = $pI-&gt;resume();
                if ($r-&gt;status === Status::Stop) {
                  unset($reg[$key]);
                }
            }
        }


        return Command::SUCCESS;
    }
}

class SuspendData
{
    public readonly Status $status;

    public function __construct($status)
    {
        $this-&gt;status = $status;
    }
}

enum Status
{
    case Stop;
    case Running;
}
</code></pre>
<p>欢迎大家补充</p>

                    
                    </div>
                </article>
            </li>
            
        </ol>
    </section>
    
</main>


        <footer class="gf-crawler-footer">
            <p><a href="/">回到首页</a> · 启用 JavaScript 以获得最佳体验。</p>
        </footer>
    </noscript>
</body>
</html>





