PHP pthreads v3下worker和pool的使用方法示例


Posted in PHP onFebruary 21, 2020

本文实例讲述了PHP pthreads v3下worker和pool的使用方法。分享给大家供大家参考,具体如下:

有些人会想,明明用thread已经可以很好的工作了,为什么还要搞个worker和pool?

之所以要用到worker和pool还是因为效率,因为系统创建一个新线程代价是比较昂贵,每个创建的线程会复制当前执行的整个上下文。

尽可能的重用线程可以让我们的程序更高效。

一个简单的worker例子:

<?php
//创建自定义work类,给work取个名字,方便查看
class Work extends Worker
{
  private $name;

  public function __construct($name)
  {
    $this->name = $name;
  }

  public function getName()
  {
    return $this->name;
  }
}

class Task extends Thread
{
  private $num;

  public function __construct($num)
  {
    $this->num = $num;
  }

  public function run()
  {
    //计算累加和
    $total = 0;
    for ($i = 0; $i < $this->num; $i++) {
      $total += $i;
    }
    echo "work : {$this->worker->getName()} task : {$total} \n";
    sleep(1);
  }
}

//创建一个worker线程
$work = new Work('a');

$work->start();

for ($i = 1; $i <= 10; $i++) {
  //将Task对象压栈到worker线程中
  //这个时候Task对象就可以使用worker线程上下文(变量,函数等)
  $work->stack(new Task($i));
}

//循环的清理任务,会阻塞主线程,直到栈中任务都执行完毕
while ($work->collect()) ;

//关闭worker
$work->shutdown();

上面代码在运行的时候,计算结果会每隔一秒出来一条,也就是10个task对象是运行在1个worker线程上的。

如果10个task对象是分别在独立空间运行的,sleep()函数就不会起作用,他们各自sleep并不会影响其他线程。

PHP pthreads v3下worker和pool的使用方法示例

把上面的代码修改一下:

<?php
//创建自定义work类,给work取个名字,方便查看
class Work extends Worker
{
  private $name;

  public function __construct($name)
  {
    $this->name = $name;
  }

  public function getName()
  {
    return $this->name;
  }
}

class Task extends Thread
{
  private $num;

  public function __construct($num)
  {
    $this->num = $num;
  }

  public function run()
  {
    //计算累加和
    $total = 0;
    for ($i = 0; $i < $this->num; $i++) {
      $total += $i;
    }
    echo "work : {$this->worker->getName()} task : {$total} \n";
    sleep(1);
  }
}

//创建二个worker线程
$work1 = new Work('a');
$work2 = new Work('b');

$work1->start();
$work2->start();

for ($i = 1; $i <= 10; $i++) {
  if ($i <= 5) {
    $work1->stack(new Task($i));
  } else {
    $work2->stack(new Task($i));
  }
}

//循环的清理任务,会阻塞主线程,直到栈中任务都执行完毕
while ($work1->collect() || $work2->collect()) ;

//关闭worker
$work1->shutdown();
$work2->shutdown();

这里我们创建2个worker线程,让10个task对象分别压栈到2个worker中。

这时可以看到,计算结果是一对一对的出来,说明10个task对象跑在了2个worker线程上。

PHP pthreads v3下worker和pool的使用方法示例

至于需要创建多少个worker线程,和多少个task对象,就看自已的需求了。

worker还有一个好处就是可以重用worker中的对象和方法。我们可以在worker中创建一个连接数据库对象,方便各task调用。

<?php
class DB extends Worker
{
  //注意这里设置为静态成员,pdo连接本身是不能在上下文中共享的
  //声明为静态成员,让每个worker有自已的pdo连接
  private static $db = null;
  public $msg = 'i from db';

  public function run()
  {
    self::$db = new PDO('mysql:host=192.168.33.226;port=3306;dbname=test;charset=utf8', 'root', '');
  }

  public function getDb()
  {
    return self::$db;
  }
}

class Task extends Thread
{
  private $id;
  //注意,这里不要给成员设置默认值,$result成员是线程对象是不可变的,不能被改写
  private $result;

  public function __construct($id)
  {
    $this->id = $id;
  }

  public function run()
  {
    //获取worker中的数据库连接
    $db = $this->worker->getDb();
    $ret = $db->query("select * from tb_user where id = {$this->id}");
    $this->result = $ret->fetch(PDO::FETCH_ASSOC);
    //访问worker中的成员变量msg
    echo "data : {$this->result['id']} {$this->result['name']} \t worker data : {$this->worker->msg} \n";
  }
}

//创建一个worker线程
$work = new DB();

$work->start();

for ($i = 1; $i <= 5; $i++) {
  $work->stack(new Task($i));
}

//循环的清理任务,会阻塞主线程,直到栈中任务都执行完毕
while ($work->collect()) ;

//关闭worker
$work->shutdown();

tb_user表大家可以随意创建,我这里为了演示只创建了id和name字段

运行结果如下:

PHP pthreads v3下worker和pool的使用方法示例

 

如果说worker是对线程的重用,那么pool就是对worker更高的抽象了,可以同时管理多个worker。

<?php
//之所以要创建一个Id线程类,主要是为了给work取个不同的ID,方便查看,哪些task线程属于哪个work中
class Id extends Thread
{
  private $id;

  public function getId()
  {
    //防止出现id混乱,这里使用同步操作
    $this->synchronized(function () {
      ++$this->id;
    });
    return $this->id;
  }
}

class Work extends Worker
{
  private $id;

  public function __construct(Id $obj)
  {
    $this->id = $obj->getId();
  }

  public function getId()
  {
    return $this->id;
  }
}

class Task extends Thread
{
  private $num = 0;

  public function __construct($num)
  {
    $this->num = $num;
  }

  //计算累加和
  public function run()
  {
    $total = 0;
    for ($i = 0; $i < $this->num; $i++) {
      $total += $i;
    }
    echo "work id : {$this->worker->getId()} task : {$total} \n";
  }
}

//创建pool,可容纳3个work对象
$pool = new Pool(3, 'Work', [new Id()]);

//循环的把20个task线程提交到pool中的work对象上运行
for ($i = 1; $i <= 20; $i++) {
  $pool->submit(new Task($i));
}

//循环的清理任务,会阻塞主线程,直到任务都执行完毕
while ($pool->collect()) ;

//关闭pool
$pool->shutdown();

运行结果如下:

PHP pthreads v3下worker和pool的使用方法示例

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
社区(php&amp;&amp;mysql)一
Oct 09 PHP
一个用于网络的工具函数库
Oct 09 PHP
PHP中设置时区,记录日志文件的实现代码
Jan 07 PHP
PHP下使用CURL方式POST数据至API接口的代码
Feb 14 PHP
PHP中判断变量为空的几种方法小结
Nov 12 PHP
php调用KyotoTycoon简单实例
Apr 02 PHP
phpMyAdmin安装并配置允许空密码登录
Jul 04 PHP
PHP正则表达式之捕获组与非捕获组
Nov 06 PHP
PHP+Ajax无刷新带进度条图片上传示例
Feb 08 PHP
PHP PDOStatement::closeCursor讲解
Jan 30 PHP
浅谈php的TS和NTS的区别
Mar 13 PHP
解决PhpStorm64不能启动的问题
Jun 20 PHP
PHP pthreads v3下同步处理synchronized用法示例
Feb 21 #PHP
PHP pthreads v3下的Volatile简介与使用方法示例
Feb 21 #PHP
PHP pthreads v3使用中的一些坑和注意点分析
Feb 21 #PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
Feb 21 #PHP
php操作redis数据库常见方法实例总结
Feb 20 #PHP
php使用redis的几种常见操作方式和用法示例
Feb 20 #PHP
PHP使用openssl扩展实现加解密方法示例
Feb 20 #PHP
You might like
JS 网站性能优化笔记
2011/05/24 PHP
PHP curl 抓取AJAX异步内容示例
2014/09/09 PHP
php+ajax登录跳转登录实现思路
2016/07/31 PHP
php判断是否为ajax请求的方法
2016/11/29 PHP
用Javascript数组处理多个字符串的连接问题
2009/08/20 Javascript
javascript小组件 原生table排序表格脚本(兼容ie firefox opera chrome)
2012/07/25 Javascript
JavaScript版TAB选项卡效果实例
2013/08/16 Javascript
Javascript 浮点运算的问题分析与解决方法
2013/08/27 Javascript
火狐下table中创建form导致两个table之间出现空白
2013/09/02 Javascript
js实现div的切换特效上一个下一个
2014/02/11 Javascript
多个checkbox被选中时如何判断是否有自己想要的
2014/09/22 Javascript
基于jQuery实现复选框的全选 全不选 反选功能
2014/11/24 Javascript
javascript实现可键盘控制的抽奖系统
2016/03/10 Javascript
BootStrap实现邮件列表的分页和模态框添加邮件的功能
2016/10/13 Javascript
详解使用JS如何制作简单的ASCII图与单极图
2017/03/31 Javascript
jQuery简介_动力节点Java学院整理
2017/07/04 jQuery
深入研究React中setState源码
2017/11/17 Javascript
webpack3里使用uglifyjs压缩js时打包报错的解决
2018/12/13 Javascript
vue实现绑定事件的方法实例代码详解
2019/06/20 Javascript
Python实现的简单发送邮件脚本分享
2014/11/07 Python
Python使用turtule画五角星的方法
2015/07/09 Python
python开发之for循环操作实例详解
2015/11/12 Python
python爬虫中get和post方法介绍以及cookie作用
2018/02/08 Python
Python常用模块之requests模块用法分析
2019/05/15 Python
python的几种矩阵相乘的公式详解
2019/07/10 Python
python实现的读取网页并分词功能示例
2019/10/29 Python
VSCode中自动为Python文件添加头部注释
2019/11/14 Python
appium+python adb常用命令分享
2020/03/06 Python
Django中Aggregation聚合的基本使用方法
2020/07/09 Python
CSS3颜色值RGBA与渐变色使用介绍
2020/03/06 HTML / CSS
中国跨境海淘网站:考拉海购
2016/08/01 全球购物
大学生应聘推荐信范文
2013/11/19 职场文书
大学生赌博检讨书
2014/09/22 职场文书
民事诉讼答辩状范文
2015/05/21 职场文书
2015年乡镇食品安全工作总结
2015/10/22 职场文书
晶体管单管来复再生式收音机
2021/04/22 无线电