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中使用Oracle数据库(3)
Oct 09 PHP
封装一个PDO数据库操作类代码
Sep 09 PHP
那些年一起学习的PHP(二)
Mar 21 PHP
PHP使用DES进行加密与解密的方法详解
Jun 06 PHP
深入file_get_contents函数抓取内容失败的原因分析
Jun 25 PHP
php实现图片局部打马赛克的方法
Feb 11 PHP
高质量PHP代码的50个实用技巧必备(下)
Jan 22 PHP
ThinkPHP的SAE开发相关注意事项详解
Oct 09 PHP
php表单处理操作
Nov 16 PHP
PHP设计模式之抽象工厂模式实例分析
Mar 25 PHP
PHP创建XML的方法示例【基于DOMDocument类及SimpleXMLElement类】
Sep 10 PHP
PHP7 新增功能
Mar 09 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
使用PHP制作新闻系统的思路
2006/10/09 PHP
UTF8编码内的繁简转换的PHP类
2009/07/09 PHP
免费手机号码归属地API查询接口和PHP使用实例分享
2014/04/10 PHP
Laravel中使用阿里云OSS Composer包分享
2015/02/10 PHP
php使用explode()函数将字符串拆分成数组的方法
2015/02/17 PHP
PHP防止刷新重复提交页面的示例代码
2015/11/11 PHP
30个精美的jQuery幻灯片效果插件和教程
2011/08/23 Javascript
JavaScript字符串对象charAt方法入门实例(用于取得指定位置的字符)
2014/10/17 Javascript
js控制鼠标事件移动及移出效果显示
2014/10/19 Javascript
javascript随机显示背景图片的方法
2015/06/18 Javascript
基于Arcgis for javascript实现百度地图ABCD marker的效果
2015/09/12 Javascript
jQuery扩展+xml实现表单验证功能的方法
2016/12/25 Javascript
在原生不支持的旧环境中添加兼容的Object.keys实现方法
2017/09/11 Javascript
浅谈在Vue-cli里基于axios封装复用请求
2017/11/06 Javascript
微信小程序实现单选选项卡切换效果
2020/06/19 Javascript
jquery实现的分页显示功能示例
2019/08/23 jQuery
JS面向对象编程基础篇(三) 继承操作实例详解
2020/03/03 Javascript
[01:39]2014DOTA2国际邀请赛 Newbee经理CU专访队伍火力全开
2014/07/15 DOTA
Python脚本暴力破解栅栏密码
2015/10/19 Python
python入门教程之识别验证码
2017/03/04 Python
pyenv命令管理多个Python版本
2017/03/26 Python
Python DataFrame 设置输出不显示index(索引)值的方法
2018/06/07 Python
Python功能点实现:函数级/代码块级计时器
2019/01/02 Python
pycharm设置python文件模板信息过程图解
2020/03/10 Python
python 爬取小说并下载的示例
2020/12/07 Python
免费获得微软MCSD证书赶快行动吧!
2012/11/13 HTML / CSS
HTML5实现的图片无限加载的瀑布流效果另带边框圆角阴影
2014/03/07 HTML / CSS
Bed Bath & Beyond加拿大官网:购买床上用品、浴巾、厨房电器等
2019/10/04 全球购物
澳大利亚电商Catch新西兰站:Catch.co.nz
2020/05/30 全球购物
请说出几个常用的异常类
2013/01/08 面试题
高中的自我鉴定
2013/12/16 职场文书
《胡杨》教学反思
2014/02/16 职场文书
迟到检讨书2000字(精选篇)
2014/10/07 职场文书
医院岗前培训心得体会
2016/01/08 职场文书
只用40行Python代码就能写出pdf转word小工具
2021/05/31 Python
JavaScript parseInt0.0000005打印5原理解析
2022/07/23 Javascript