V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
onanying
V2EX  ›  PHP

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

  •  
  •   onanying · 2019-04-16 20:22:28 +08:00 · 3055 次点击
    这是一个创建于 2073 天前的主题,其中的信息可能已经有所发展或是发生改变。

    协程

    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 <[email protected]>
     */
    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 <[email protected]>
     */
    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 一直处于阻塞状态。

    定时器

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

    • Timer::new() 可获得一个实例
    • after 方法可设置一次性定时
    • tick 方法可设置持续定时
    • 停止当前定时期,只需只需对象的 $timer->clear(); 方法。
    <?php
    
    namespace Console\Commands;
    
    use Mix\Core\Event;
    use Mix\Core\Timer;
    
    /**
     * Class TimerCommand
     * @package Console\Commands
     * @author liu,jian <[email protected]>
     */
    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

    4 条回复    2019-04-22 19:05:41 +08:00
    onanying
        1
    onanying  
    OP
       2019-04-18 16:50:42 +08:00
    尴尬,为何没有回复?
    ETO
        2
    ETO  
       2019-04-19 08:53:01 +08:00
    表示有点不太看得懂,最近准备看一下 swool 相关的东西。
    dvaknheo
        3
    dvaknheo  
       2019-04-21 16:52:35 +08:00
    没看出 和 Swoole 原生的相比改进了什么
    onanying
        4
    onanying  
    OP
       2019-04-22 19:05:41 +08:00
    @dvaknheo 提供了连接池,协程池这些 swoole 不会提供的,还有 Ioc 等其他很多不过和这个文章无关就不说了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   935 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 22:06 · PVG 06:06 · LAX 14:06 · JFK 17:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.