Mix PHP V2 新特性:协程、定时器

2019-04-16 20:22:28 +08:00
 onanying

协程

Mix PHP V2 基于 Swoole 4 的 PHP Stream Hook 协程技术开发,协程使用方式与 Golang 几乎一致,包括框架封装的协程池、连接池、命令行处理都大量参考了 Golang 的系统库风格。

除了缺少 select case 外,Mix PHP 与 Golang 的协程几乎一致,框架还提供了连接池、协程池、命令行处理这些开箱即用的封装。

xgo + Channel

xgo 类似 Golang 的 go 关键字,可启动一个新的协程,Channel 等于 Golang 的 chan 类,负责在不同协程中传递数据。

<?php

namespace Console\Commands;

use Mix\Core\Coroutine\Channel;
use Mix\Core\Event;

/**
 * Class CoroutineCommand
 * @package Console\Commands
 * @author liu,jian <coder.keda@gmail.com>
 */
class CoroutineCommand
{

    /**
     * 主函数
     */
    public function main()
    {
        xgo(function () {
            $time = time();
            $chan = new Channel();
            for ($i = 0; $i < 2; $i++) {
                xgo([$this, 'foo'], $chan);
            }
            for ($i = 0; $i < 2; $i++) {
                $result = $chan->pop();
            }
            println('Total time: ' . (time() - $time));
        });
        Event::wait();
    }

    /**
     * 查询数据
     * @param Channel $chan
     */
    public function foo(Channel $chan)
    {
        $db     = app()->dbPool->getConnection();
        $result = $db->createCommand('select sleep(5)')->queryAll();
        $db->release(); // 不手动释放的连接不会归还连接池,会在析构时丢弃
        $chan->push($result);
    }

}

执行结果为 5s,说明是并行执行的。

WaitGroup + xdefer

WaitGroup 与 Golang 的完全一致,xdefer 方法也等同于 Golang 的 defer 关键字。

当并行执行且不需要返回结果时,可以使用 WaitGroup + xdefer,xdefer 即使在方法抛出异常时,仍然会执行,这样能避免一直处于阻塞状态。

<?php

namespace Console\Commands;

use Mix\Concurrent\Sync\WaitGroup;
use Mix\Core\Event;

/**
 * Class WaitGroupCommand
 * @package Console\Commands
 * @author liu,jian <coder.keda@gmail.com>
 */
class WaitGroupCommand
{

    /**
     * 主函数
     */
    public function main()
    {
        xgo(function () {
            $wg = WaitGroup::new();
            for ($i = 0; $i < 2; $i++) {
                $wg->add(1);
                xgo([$this, 'foo'], $wg);
            }
            $wg->wait();
            println('All done!');
        });
        Event::wait();
    }

    /**
     * 查询数据
     * @param WaitGroup $wg
     */
    public function foo(WaitGroup $wg)
    {
        xdefer(function () use ($wg) {
            $wg->done();
        });
        println('work');
        throw new \RuntimeException('ERROR');
    }

}

即便抛出了 RuntimeException 异常,仍然能执行到 println('All done!');,没有导致 wg 内的 chan 一直处于阻塞状态。

定时器

异步编程中,定时器的使用非常频繁。

<?php

namespace Console\Commands;

use Mix\Core\Event;
use Mix\Core\Timer;

/**
 * Class TimerCommand
 * @package Console\Commands
 * @author liu,jian <coder.keda@gmail.com>
 */
class TimerCommand
{

    /**
     * 主函数
     */
    public function main()
    {
        // 一次性定时
        Timer::new()->after(1000, function () {
            println(time());
        });

        // 持续定时
        $timer = new Timer();
        $timer->tick(1000, function () {
            println(time());
        });

        // 停止定时
        Timer::new()->after(10000, function () use ($timer) {
            $timer->clear();
        });

        Event::wait();
    }

}

GitHub

支持的用户请加个 Star 吧,让更多人发现 MixPHP。https://github.com/mix-php/mix

2917 次点击
所在节点    PHP
4 条回复
onanying
2019-04-18 16:50:42 +08:00
尴尬,为何没有回复?
ETO
2019-04-19 08:53:01 +08:00
表示有点不太看得懂,最近准备看一下 swool 相关的东西。
dvaknheo
2019-04-21 16:52:35 +08:00
没看出 和 Swoole 原生的相比改进了什么
onanying
2019-04-22 19:05:41 +08:00
@dvaknheo 提供了连接池,协程池这些 swoole 不会提供的,还有 Ioc 等其他很多不过和这个文章无关就不说了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/555805

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX