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开发GUI
Oct 09 PHP
PHP导出MySQL数据到Excel文件(fputcsv)
Jul 03 PHP
php多文件上传下载示例分享
Feb 20 PHP
PHP把网页保存为word文件的三种方法
Apr 01 PHP
ThinkPHP之getField详解
Jun 20 PHP
destoon二次开发模板及调用语法汇总
Jun 21 PHP
php 使用file_get_contents读取大文件的方法
Nov 13 PHP
PHP程序员必须清楚的问题汇总
Dec 18 PHP
php数组添加与删除单元的常用函数实例分析
Feb 16 PHP
避免Smarty与CSS语法冲突的方法
Mar 02 PHP
全面解析PHP验证码的实现原理 附php验证码小案例
Aug 17 PHP
php计数排序算法的实现代码(附四个实例代码)
Mar 31 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内存相关的功能特性详解
2013/06/08 PHP
基于empty函数的输出详解
2013/06/17 PHP
限制ckeditor上传图片文件大小的方法
2013/11/15 PHP
PHP魔术方法的使用示例
2015/06/23 PHP
PHP实现多维数组转字符串和多维数组转一维数组的方法
2015/08/08 PHP
Symfony2安装第三方Bundles实例详解
2016/02/04 PHP
ThinkPHP3.2.1图片验证码实现方法
2016/08/19 PHP
Thinkphp结合ajaxFileUpload实现异步图片传输示例
2017/03/13 PHP
PHP基于GD库实现的生成图片缩略图函数示例
2017/07/05 PHP
PHP防止sql注入小技巧之sql预处理原理与实现方法分析
2019/12/13 PHP
JavaScript实际应用:innerHTMl和确认提示的使用
2006/06/22 Javascript
javascript FormatNumber函数实现方法
2008/12/30 Javascript
jQuery下拉友情链接美化效果代码分享
2015/08/26 Javascript
js+css实现超简洁的二级下拉菜单效果代码
2015/09/07 Javascript
jQuery文字提示与图片提示效果实现方法
2016/07/04 Javascript
AngularJS基础 ng-focus 指令简单示例
2016/08/01 Javascript
switch语句的妙用(必看篇)
2016/10/03 Javascript
微信小程序本地缓存数据增删改查实例详解
2017/05/24 Javascript
vue使用原生js实现滚动页面跟踪导航高亮的示例代码
2018/10/25 Javascript
jQuery动态操作表单示例【基于table表格】
2018/12/06 jQuery
JavaScript实现点击切换功能
2021/01/27 Javascript
[06:11]2014DOTA2国际邀请赛 专访团结一心的VG战队
2014/07/21 DOTA
python函数参数*args**kwargs用法实例
2013/12/04 Python
django-orm F对象的使用 按照两个字段的和,乘积排序实例
2020/05/18 Python
pycharm远程连接vagrant虚拟机中mariadb数据库
2020/06/05 Python
css3实现3D色子翻转特效
2014/12/23 HTML / CSS
CSS3制作缩略图的详细过程
2016/07/08 HTML / CSS
CSS3实现王者匹配时的粒子动画效果
2019/04/12 HTML / CSS
Linux上比较文件的命令都有哪些
2013/09/28 面试题
建筑设计所实习生自我鉴定
2013/09/25 职场文书
环境工程专业自荐信范文
2014/06/24 职场文书
会计电算化实训报告
2014/11/04 职场文书
爱牙日宣传活动总结
2015/02/05 职场文书
Python实现文本文件拆分写入到多个文本文件的方法
2021/04/18 Python
pytorch中的model=model.to(device)使用说明
2021/05/24 Python
python模块与C和C++动态库相互调用实现过程示例
2021/11/02 Python