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.MVC的模板标签系统(三)
Sep 05 PHP
一个可查询所有表的“通用”查询分页类
Oct 09 PHP
建立动态的WML站点(三)
Oct 09 PHP
在PHP中实现Javascript的escape()函数代码
Aug 08 PHP
php中防止恶意刷新页面的代码小结
Oct 31 PHP
解析php下载远程图片函数 可伪造来路
Jun 25 PHP
php顺序查找和二分查找示例
Mar 27 PHP
php rsa加密解密使用详解
Jan 14 PHP
php短网址和数字之间相互转换的方法
Mar 13 PHP
PHP实现递归无限级分类
Oct 22 PHP
基于PHP的加载类操作以及其他两种魔术方法的应用实例
Aug 28 PHP
php curl批处理实现可控并发异步操作示例
May 09 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效率,提高php性能的一些方法
2011/03/24 PHP
php中的注释、变量、数组、常量、函数应用介绍
2012/11/16 PHP
php校验公钥是否可用的实例方法
2019/09/17 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/02/09 Javascript
javascript写的日历类(基于pj)
2010/12/28 Javascript
jquery $.each 和for怎么跳出循环终止本次循环
2013/09/27 Javascript
jQuery异步提交表单的两种方式
2016/09/13 Javascript
chrome下判断点击input上标签还是其余标签的实现方法
2016/09/18 Javascript
Angular 常用指令实例总结整理
2016/12/13 Javascript
javascript遍历json对象的key和任意js对象属性实例
2017/03/09 Javascript
JS判断两个对象内容是否相等的方法示例
2017/04/10 Javascript
vue router路由嵌套不显示问题的解决方法
2017/06/17 Javascript
vue2导航根据路由传值,而改变导航内容的实例
2017/11/10 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
2018/10/30 Javascript
Vue组件的使用及个人理解与介绍
2019/02/09 Javascript
详解在React项目中安装并使用Less(用法总结)
2019/03/18 Javascript
浅析JavaScript预编译和暗示全局变量
2020/09/03 Javascript
使用Kivy将python程序打包为apk文件
2017/07/29 Python
使用python实现knn算法
2017/12/20 Python
python内置数据类型之列表操作
2018/11/12 Python
django中SMTP发送邮件配置详解
2019/07/19 Python
Python学习笔记之Zip和Enumerate用法实例分析
2019/08/14 Python
Python实现手机号自动判断男女性别(实例解析)
2019/12/22 Python
完美解决keras 读取多个hdf5文件进行训练的问题
2020/07/01 Python
Python迭代器协议及for循环工作机制详解
2020/07/14 Python
如何用PyPy让你的Python代码运行得更快
2020/12/02 Python
Python 实现进度条的六种方式
2021/01/06 Python
澳大利亚第一的设计师礼服租赁网站:GlamCorner
2017/08/13 全球购物
英国健身仓库:Bodybuilding Warehouse
2019/03/06 全球购物
护士实习鉴定范文
2013/12/22 职场文书
预备党员思想汇报范文
2013/12/29 职场文书
自动化专业个人求职信范文
2013/12/30 职场文书
党的群众路线教育实践活动剖析材料
2014/09/30 职场文书
离婚答辩状怎么写
2015/05/22 职场文书
详解Java实践之适配器模式
2021/06/18 Java/Android
JavaScript中MutationObServer监听DOM元素详情
2021/11/27 Javascript