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 cookis创建实现代码
Mar 16 PHP
apache2.2.4+mysql5.0.77+php5.2.8安装精简
Apr 29 PHP
判断PHP数组是否为空的代码
Sep 08 PHP
url decode problem 解决方法
Dec 26 PHP
解析linux下安装memcacheq(mcq)全过程笔记
Jun 27 PHP
使用PHP实现Mysql读写分离
Jun 28 PHP
设置php页面编码的两种方法示例介绍
Mar 03 PHP
ThinkPHP3.1新特性之命名范围的使用
Jun 19 PHP
朋友网关于QQ相关的PHP代码(研究QQ的绝佳资料)
Jan 26 PHP
THINKPHP支持YAML配置文件的设置方法
Mar 17 PHP
详解配置 Apache 服务器支持 PHP 文件的解析
Feb 15 PHP
PHP文件管理之实现网盘及压缩包的功能操作
Sep 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
用PHP和ACCESS写聊天室(二)
2006/10/09 PHP
解析PHP中的unset究竟会不会释放内存
2013/07/18 PHP
PHP函数strip_tags的一个bug浅析
2014/05/22 PHP
php基于表单密码验证与HTTP验证用法实例
2015/01/06 PHP
PHP扩展Memcache分布式部署方案
2015/12/06 PHP
php数据访问之查询关键字
2016/05/09 PHP
Aster vs Newbee BO5 第二场2.19
2021/03/10 DOTA
bcastr2.0 通用的图片浏览器
2006/11/22 Javascript
javascript indexOf函数使用说明
2008/07/03 Javascript
jquery如何改变html标签的样式(两种实现方法)
2013/01/16 Javascript
JS 在指定数组中随机取出N个不重复的数据
2014/06/10 Javascript
javascript实现表单提交后,提交按钮不可用的方法
2015/04/18 Javascript
JQuery实现级联下拉框效果实例讲解
2015/09/17 Javascript
Javascript 基础---Ajax入门必看
2016/07/06 Javascript
JavaScript String(字符串)对象的简单实例(推荐)
2016/08/31 Javascript
JS中传递参数的几种不同方法比较
2017/01/20 Javascript
js以及jquery实现手风琴效果
2020/04/17 Javascript
js实现登录注册框手机号和验证码校验(前端部分)
2017/09/28 Javascript
除Console.log()外更多的Javascript调试命令
2018/01/24 Javascript
微信小程序button组件使用详解
2018/01/31 Javascript
用Node提供静态文件服务的方法
2018/07/06 Javascript
[45:40]Ti4 冒泡赛第二天NEWBEE vs NaVi 1
2014/07/15 DOTA
Python中使用bidict模块双向字典结构的奇技淫巧
2016/07/12 Python
基于Python3 逗号代码 和 字符图网格(详谈)
2017/06/22 Python
Python3 获取一大段文本之间两个关键字之间的内容方法
2018/10/11 Python
Python中请不要再用re.compile了
2019/06/30 Python
Django REST framework 单元测试实例解析
2019/11/07 Python
Python 格式化输出_String Formatting_控制小数点位数的实例详解
2020/02/04 Python
Python连接mysql数据库及简单增删改查操作示例代码
2020/08/03 Python
英国DIY和家居装饰领域的主要品牌:Wickes
2019/11/26 全球购物
启动一个线程是用run()还是start()
2016/12/25 面试题
电气工程及自动化专业自荐书范文
2013/12/18 职场文书
房屋继承公证书
2014/04/10 职场文书
巾帼志愿者活动方案
2014/08/17 职场文书
2015学习委员工作总结范文
2015/04/03 职场文书
图书借阅制度范本
2015/08/06 职场文书