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 相关文章推荐
模拟flock实现文件锁定
Feb 14 PHP
php 函数中使用static的说明
Jun 01 PHP
php循环语句 for()与foreach()用法区别介绍
Sep 05 PHP
使用PHP计算两个路径的相对路径
Jun 14 PHP
PHP实现简单搜歌的方法
Jul 28 PHP
利用PHP将部分内容用星号替换
Apr 21 PHP
ThinkPHP3.2.1图片验证码实现方法
Aug 19 PHP
ThinkPHP使用getlist方法实现数据搜索功能示例
May 08 PHP
PHP实现阿里大鱼短信验证的实例代码
Jul 10 PHP
微信公众号实现扫码获取微信用户信息(网页授权)
Apr 09 PHP
ThinkPHP 5 AJAX跨域请求头设置实现过程解析
Oct 28 PHP
php随机生成验证码,php随机生成数字,php随机生成数字加字母!
Apr 01 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
给海燕B411配件机起死回生配上件
2021/03/02 无线电
php下用GD生成生成缩略图的两个选择和区别
2007/04/17 PHP
解析PHP汉字转换拼音的类
2013/06/18 PHP
PDO::setAttribute讲解
2019/01/29 PHP
关于PhpStorm设置点击编辑文件自动定位源文件的实现方式
2020/12/30 PHP
JavaScript TO HTML 转换
2006/06/26 Javascript
JavaScript入门教程(2) JS基础知识
2009/01/31 Javascript
JavaScript让IE浏览器event对象符合W3C DOM标准
2009/11/24 Javascript
用js实现层随着内容大小动态渐变改变 推荐
2009/12/19 Javascript
js通过八个点 拖动改变div大小的实现方法
2014/03/05 Javascript
node.js中的buffer.write方法使用说明
2014/12/10 Javascript
cookie的secure属性详解
2015/04/08 Javascript
jQuery实现可移动选项的左右下拉列表示例
2016/12/26 Javascript
jQuery中ztree 点击文本框弹出下拉框的实例代码
2017/02/05 Javascript
nodejs实现截取上传视频中一帧作为预览图片
2017/12/10 NodeJs
vue-cli webpack 引入jquery的方法
2018/01/10 jQuery
纯js封装的ajax功能函数与用法示例
2018/05/14 Javascript
VUE2.0 ElementUI2.0表格el-table自适应高度的实现方法
2018/11/28 Javascript
javascript实现搜索筛选功能实例代码
2020/11/12 Javascript
压缩包密码破解示例分享(类似典破解)
2014/01/17 Python
python字符串加密解密的三种方法分享(base64 win32com)
2014/01/19 Python
Django中使用locals()函数的技巧
2015/07/16 Python
Python 使用SMTP发送邮件的代码小结
2016/09/21 Python
python中正则表达式 re.findall 用法
2018/10/23 Python
python 重命名轴索引的方法
2018/11/10 Python
Appium+python自动化之连接模拟器并启动淘宝APP(超详解)
2019/06/17 Python
django 单表操作实例详解
2019/07/30 Python
Python telnet登陆功能实现代码
2020/04/16 Python
PyCharm2020.1.2社区版安装,配置及使用教程详解(Windows)
2020/08/07 Python
python全栈开发语法总结
2020/11/22 Python
请说出几个常用的异常类
2013/01/08 面试题
小学班主任评语大全
2014/04/23 职场文书
对党的十八届四中全会的期盼
2014/10/17 职场文书
2015年财务人员工作总结
2015/04/10 职场文书
销售人员管理制度
2015/08/06 职场文书
2016年乡镇七一建党节活动总结
2016/04/05 职场文书