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中通过smtp发邮件的类,测试通过
Jan 22 PHP
PHP 中文乱码解决办法总结分析
Jul 30 PHP
在字符串指定位置插入一段字符串的php代码
Feb 16 PHP
php牛逼的面试题分享
Jan 18 PHP
PHP中4个加速、缓存扩展的区别和选用建议
Mar 12 PHP
PHP获取文件行数的方法
Jun 10 PHP
ECshop 迁移到 PHP7版本时遇到的兼容性问题
Feb 15 PHP
nginx下安装php7+php5
Jul 31 PHP
php redis实现对200w用户的即时推送
Mar 04 PHP
原生JS实现Ajax通过POST方式与PHP进行交互的方法示例
May 12 PHP
ThinkPHP框架结合Ajax实现用户名校验功能示例
Jul 03 PHP
laravel orm 关联条件查询代码
Oct 21 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/10/28 PHP
curl实现站外采集的方法和技巧
2014/01/31 PHP
采用header定义为文件然后readfile下载(隐藏下载地址)
2014/01/31 PHP
Yii中创建自己的Widget实例
2016/01/05 PHP
php递归函数怎么用才有效
2018/02/24 PHP
php探针使用原理和技巧讲解
2019/09/17 PHP
有效的捕获JavaScript焦点的方法小结
2009/10/08 Javascript
初试jQuery EasyUI 使用介绍
2010/04/01 Javascript
圣诞节Merry Christmas给博客添加浪漫的下雪效果基于jquery实现
2012/12/27 Javascript
信息页文内画中画广告js实现代码(文中加载广告方式)
2016/01/03 Javascript
基于JavaScript实现简单的随机抽奖小程序
2016/01/05 Javascript
理解JS绑定事件
2016/01/19 Javascript
基于jQuery实现音乐播放试听列表
2016/04/14 Javascript
pc加载更多功能和移动端下拉刷新加载数据
2016/11/07 Javascript
基于Vue过渡状态实例讲解
2017/09/14 Javascript
AngularJS使用ng-repeat遍历二维数组元素的方法详解
2017/11/11 Javascript
微信小程序实现YDUI的ScrollNav组件
2018/02/02 Javascript
在vscode中统一vue编码风格的方法
2018/02/22 Javascript
Vue自定义过滤器格式化数字三位加一逗号实现代码
2018/03/23 Javascript
Node.js + express基本用法教程
2019/03/14 Javascript
一个手写的vue放大镜效果
2019/08/09 Javascript
Vue 实现一个命令式弹窗组件功能
2019/09/25 Javascript
jquery 遍历hash操作示例【基于ajax交互】
2019/10/12 jQuery
如何使用gpu.js改善JavaScript的性能
2020/12/01 Javascript
js用正则表达式筛选年月日的实例方法
2021/01/04 Javascript
[01:07:41]IG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python实现简单遗传算法
2018/03/19 Python
python学习笔记--将python源文件打包成exe文件(pyinstaller)
2018/05/26 Python
Python字符串hashlib加密模块使用案例
2020/03/10 Python
CSS3动画效果回调处理详解
2014/12/10 HTML / CSS
What's the difference between an interface and abstract class? (接口与抽象类有什么区别)
2012/10/29 面试题
最新奶茶店创业计划书
2014/01/25 职场文书
餐饮企业总经理岗位职责范文
2014/02/18 职场文书
保护环境的建议书
2014/03/12 职场文书
读鲁迅先生的经典名言
2019/08/20 职场文书
AI:如何训练机器学习的模型
2021/04/16 Python