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中使用模板的方法
May 24 PHP
PHP url 加密解密函数代码
Aug 26 PHP
基于PHP 面向对象之成员方法详解
May 04 PHP
PHP计算一年多少个星期和每周的开始和结束日期
Jul 01 PHP
PHP伪静态Rewrite设置之APACHE篇
Jul 30 PHP
PHP命名空间(namespace)的动态访问及使用技巧
Aug 18 PHP
php+mysqli使用面向对象方式查询数据库实例
Jan 29 PHP
浅谈PHP中output_buffering
Jul 13 PHP
thinkPHP2.1自定义标签库的导入方法详解
Jul 20 PHP
php实现的错误处理封装类实例
Jun 20 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
Aug 31 PHP
php和js实现根据子网掩码和ip计算子网功能示例
Nov 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类的使用 实例代码讲解
2009/12/28 PHP
php版小黄鸡simsimi聊天机器人接口分享
2014/01/26 PHP
Laravel框架实现发送短信验证功能代码
2016/06/06 PHP
Windows平台实现PHP连接SQL Server2008的方法
2017/07/26 PHP
jQuery的实现原理的模拟代码 -5 Ajax
2010/08/07 Javascript
Javascript表格翻页效果的具体实现
2013/10/05 Javascript
js对列表中第一个值处理与jsp页面对列表中第一个值处理的区别详解
2013/11/05 Javascript
解决jquery1.9不支持browser对象的问题
2013/11/13 Javascript
完美兼容IE,chrome,ff的设为首页、加入收藏及保存到桌面js代码
2014/12/17 Javascript
GitHub上一些实用的JavaScript的文件压缩解压缩库推荐
2016/03/13 Javascript
用js控件div的滚动条,让它在内容更新时自动滚到底部的实现方法
2016/10/27 Javascript
微信小程序使用audio组件播放音乐功能示例【附源码下载】
2017/12/08 Javascript
详解vue的diff算法原理
2018/05/20 Javascript
angular6的table组件开发的实现示例
2018/12/26 Javascript
vue-cli3使用 DllPlugin 实现预编译提升构建速度
2019/04/24 Javascript
Javascript读取上传文件内容/类型/字节数
2019/04/30 Javascript
Vue中错误图片的处理的实现代码
2019/11/07 Javascript
JS算法教程之字符串去重与字符串反转
2020/12/15 Javascript
[59:07]海涛为你详解DOTA2新版本“贤哲秘契”
2014/11/22 DOTA
python多线程编程中的join函数使用心得
2014/09/02 Python
深入探究Python中变量的拷贝和作用域问题
2015/05/05 Python
python MysqlDb模块安装及其使用详解
2018/02/23 Python
Python第三方Window模块文件的几种安装方法
2018/11/22 Python
基于python实现名片管理系统
2018/11/30 Python
快速解决pyqt5窗体关闭后子线程不同时退出的问题
2019/06/19 Python
Python3视频转字符动画的实例代码
2019/08/29 Python
pytorch 中forward 的用法与解释说明
2021/02/26 Python
DNA基因检测和分析:23andMe
2019/05/01 全球购物
春风行动实施方案
2014/03/28 职场文书
学校标语大全
2014/06/19 职场文书
乌镇导游词
2015/02/02 职场文书
大学生个人年度总结范文
2015/02/15 职场文书
实验室安全管理制度
2015/08/05 职场文书
2015年大学组织委员个人工作总结
2015/10/23 职场文书
Python-OpenCV教程之图像的位运算详解
2021/06/21 Python
电脑关机速度很慢怎么办 提升电脑关机速度设置教程
2022/04/08 数码科技