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 相关文章推荐
JAVA/JSP学习系列之六
Oct 09 PHP
PHP伪静态写法附代码
Jun 20 PHP
php中对2个数组相加的函数
Jun 24 PHP
str_replace只替换一次字符串的方法
Apr 09 PHP
基于php设计模式中单例模式的应用分析
May 15 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
Nov 18 PHP
PHP实现通过get方式识别用户发送邮件的方法
Jul 16 PHP
总结PHP如何获取当前主机、域名、网址、路径、端口和参数等
Sep 09 PHP
phpinfo()中Loaded Configuration File(none)的解决方法
Jan 16 PHP
php简单中奖算法(实例)
Aug 15 PHP
详细解读php的命名空间(二)
Feb 21 PHP
基于php数组中的索引数组和关联数组详解
Mar 12 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
shopex中集成的站长统计功能的代码简单分析
2011/08/11 PHP
PHP在引号前面添加反斜杠(PHP去除反斜杠)
2013/09/28 PHP
在WordPress中获取数据库字段内容和添加主题设置菜单
2016/01/11 PHP
PHP+HTML+JavaScript+Css实现简单爬虫开发
2016/03/28 PHP
PHP记录页面停留时间的方法
2016/03/30 PHP
php实现页面纯静态的实例代码
2017/06/21 PHP
JQuery下关于$.Ready()的分析
2009/12/13 Javascript
Jquery 1.42 checkbox 全选和反选代码
2010/03/27 Javascript
jQuery下实现等待指定元素加载完毕(可改成纯js版)
2013/07/11 Javascript
js阻止冒泡及jquery阻止事件冒泡示例介绍
2013/11/19 Javascript
JS阻止冒泡事件以及默认事件发生的简单方法
2014/01/17 Javascript
动态创建script在IE中缓存js文件时导致编码的解决方法
2014/05/04 Javascript
jquery文档操作wrap()方法实例简述
2015/01/10 Javascript
javascript中基本类型和引用类型的区别分析
2015/05/12 Javascript
js实现图片无缝滚动特效
2020/03/19 Javascript
深入理解JavaScript程序中内存泄漏
2016/03/17 Javascript
JS遍历数组和对象的区别及递归遍历对象、数组、属性的方法详解
2016/06/14 Javascript
jQuery旋转插件jqueryrotate用法详解
2016/10/13 Javascript
基于BootstrapValidator的Form表单验证(24)
2016/12/12 Javascript
JS简单实现点击按钮或文字显示遮罩层的方法
2017/04/27 Javascript
Node.JS文件系统解析实例详解
2017/05/15 Javascript
微信小程序rich-text富文本用法实例分析
2019/05/20 Javascript
vue+element tabs选项卡分页效果
2020/06/29 Javascript
如何使用JavaScript检测空闲的浏览器选项卡
2020/05/28 Javascript
[03:43]2014DOTA2西雅图国际邀请赛 newbee战队巡礼
2014/07/07 DOTA
Python wxPython库Core组件BoxSizer用法示例
2018/09/03 Python
解决python 虚拟环境删除包无法加载的问题
2020/07/13 Python
捷克家居装饰及图书音像购物网站:Velký košík
2018/04/16 全球购物
法国滑雪假期的专家:Ski Planet
2019/11/02 全球购物
《列夫托尔斯泰》教学反思
2014/02/10 职场文书
服务理念口号
2014/06/11 职场文书
小学安全工作汇报材料
2014/08/19 职场文书
“向国旗敬礼”活动策划方案(4篇)
2014/09/27 职场文书
关于艺术节的开幕致辞
2016/03/04 职场文书
python requests模块的使用示例
2021/04/07 Python
你喜欢篮球吗?Python实现篮球游戏
2021/06/11 Python