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 相关文章推荐
解决dede生成静态页和动态页转换的一些问题,及火车采集入库生成动态的办法
Mar 29 PHP
php快速url重写更新版[需php 5.30以上]
Apr 25 PHP
flash用php连接数据库的代码
Apr 21 PHP
thinkphp控制器调度使用示例
Feb 24 PHP
destoon网站转移服务器后搜索汉字出现乱码的解决方法
Jun 21 PHP
PHP+Mysql基于事务处理实现转账功能的方法
Jul 08 PHP
PHP面试题之文件目录操作
Oct 15 PHP
2款PHP无限级分类实例代码
Nov 11 PHP
CodeIgniter框架常见用法工作总结
Mar 16 PHP
Laravel框架在本地虚拟机快速安装的方法详解
Jun 11 PHP
Laravel使用RabbitMQ的方法示例
Jun 18 PHP
PHP Trait功能与用法实例分析
Jun 03 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
DSP接收机前端设想
2021/03/02 无线电
浅析PHP程序防止ddos,dns,集群服务器攻击的解决办法
2013/06/18 PHP
使用php显示搜索引擎来的关键词
2014/02/13 PHP
yii的入口文件index.php中为什么会有这两句
2016/08/04 PHP
Zend Framework入门教程之Zend_Config组件用法详解
2016/12/09 PHP
让ie运行js时提示允许阻止内容运行的解决方法
2010/10/24 Javascript
js 点击页面其他地方关闭弹出层(示例代码)
2013/12/24 Javascript
CSS或者JS实现鼠标悬停显示另一元素
2016/01/22 Javascript
JS常用加密编码与算法实例总结
2016/12/22 Javascript
vue之数据交互实例代码
2017/06/16 Javascript
自定义vue组件发布到npm的方法
2018/05/09 Javascript
Vue 通过自定义指令回顾v-内置指令(小结)
2018/09/03 Javascript
vue实现百度搜索功能
2020/12/28 Javascript
javascript设计模式 ? 桥接模式原理与应用实例分析
2020/04/13 Javascript
jQuery实现的解析本地 XML 文档操作示例
2020/04/30 jQuery
Python入门_浅谈字符串的分片与索引、字符串的方法
2017/05/16 Python
python实现拓扑排序的基本教程
2018/03/11 Python
简单了解python反射机制的一些知识
2019/07/13 Python
Python装饰器使用你可能不知道的几种姿势
2019/10/25 Python
Python爬虫教程知识点总结
2020/10/19 Python
HTML5中的Scoped属性使用实例
2014/04/23 HTML / CSS
复古风格的女装和装饰品:ModCloth
2017/12/29 全球购物
Johnston & Murphy官网: 约翰斯顿·墨菲牛津总统鞋
2018/01/09 全球购物
澳洲国民品牌乡村路折扣店:Country Road & Trenery Outlet
2018/04/19 全球购物
洛杉矶健身中心女性专用运动服饰品牌:Marika
2018/05/09 全球购物
善意的谎言事例
2014/02/15 职场文书
房地产端午节活动方案
2014/08/24 职场文书
电力培训心得体会
2014/09/02 职场文书
庆六一宣传标语
2014/10/08 职场文书
硕士毕业论文导师评语
2014/12/31 职场文书
2015年部门工作总结范文
2015/03/31 职场文书
事业单位工作人员岗前培训心得体会
2016/01/08 职场文书
详解Js模块化的作用原理和方案
2021/04/29 Javascript
PyTorch的Debug指南
2021/05/07 Python
Windows server 2012 R2 安装IIS服务器
2022/04/29 Servers
python可视化分析绘制带趋势线的散点图和边缘直方图
2022/06/25 Python