首頁 後端開發 PHP8 PHP8.1 Fiber交叉執行多任務(附程式碼詳解)

PHP8.1 Fiber交叉執行多任務(附程式碼詳解)

Dec 20, 2021 am 10:49 AM

大家的電腦上所佔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 . &#39;:&#39; . $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 . &#39;:&#39; . $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: &#39;Sname&#39;,
    description: &#39;Add a short description for your command&#39;,
)]
class SnameCommand extends Command
{
    protected function configure(): void
    {
        $this
            ->addArgument(&#39;arg1&#39;, InputArgument::OPTIONAL, &#39;Argument description&#39;)
            ->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 < 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 < 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) > 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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)