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
Oct 09 PHP
用PHP函数解决SQL injection
Oct 09 PHP
php录入页面中动态从数据库中提取数据的实现
Oct 09 PHP
PHPMyAdmin 快速配置方法
May 11 PHP
PHP+MySQL 手工注入语句大全 推荐
Oct 30 PHP
一个PHP的QRcode类与大家分享
Nov 13 PHP
检查用户名是否已在mysql中存在的php写法
Jan 20 PHP
php求两个目录的相对路径示例(php获取相对路径)
Mar 27 PHP
学习php设计模式 php实现桥梁模式(bridge)
Dec 07 PHP
Zend Framework处理Json数据方法详解
Dec 09 PHP
PHP有序表查找之插值查找算法示例
Feb 10 PHP
Yii2框架自定义类统一处理url操作示例
May 25 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入门小知识
2008/03/24 PHP
php 安全过滤函数代码
2011/05/07 PHP
simplehtmldom Doc api帮助文档
2012/03/26 PHP
php生成EAN_13标准条形码实例
2013/11/13 PHP
JS判断页面加载状态以及添加遮罩和缓冲动画的代码
2012/10/11 Javascript
基于jQuery实现Div窗口震动特效代码-代码简单
2015/08/28 Javascript
JavaScript实现的SHA-1加密算法完整实例
2016/02/02 Javascript
jquery拖动层效果插件用法实例分析(附demo源码)
2016/04/28 Javascript
jQuery的Cookie封装,与PHP交互的简单实现
2016/10/05 Javascript
JS中动态创建元素的三种方法总结(推荐)
2016/10/20 Javascript
jQuery读取XML文件的方法示例
2017/02/03 Javascript
Bootstrap fileinput组件封装及使用详解
2017/03/10 Javascript
详解Vue用axios发送post请求自动set cookie
2017/05/10 Javascript
Nuxt.js实战详解
2018/01/18 Javascript
NodeJS父进程与子进程资源共享原理与实现方法
2018/03/16 NodeJs
使用Angular material主题定义自己的组件库的配色体系
2019/09/04 Javascript
vue实现顶部菜单栏
2020/11/08 Javascript
echarts柱状图背景重叠组合而非并列的实现代码
2020/12/10 Javascript
原生js实现滑块区间组件
2021/01/20 Javascript
小议Python中自定义函数的可变参数的使用及注意点
2016/06/21 Python
教大家玩转Python字符串处理的七种技巧
2017/03/31 Python
Python数学形态学实例分析
2019/09/06 Python
使用tensorflow实现VGG网络,训练mnist数据集方式
2020/05/26 Python
Python基于wordcloud及jieba实现中国地图词云图
2020/06/09 Python
详解Python 函数参数的拆解
2020/09/02 Python
多个版本的python共存时使用pip的正确做法
2020/10/26 Python
CSS3新增布局之: flex详解
2020/06/18 HTML / CSS
经济实惠的豪华背包和行李袋:Packs Project
2018/10/17 全球购物
英国顶级足球鞋的领先零售商:Lovell Soccer
2019/08/27 全球购物
Linux内核产生并发的原因
2012/07/13 面试题
【魔兽争霸3重制版】原版画面与淬火MOD画面对比
2021/03/26 魔兽争霸
早会主持词
2014/03/17 职场文书
和谐家庭演讲稿
2014/05/24 职场文书
世界文化遗产导游词
2019/08/07 职场文书
解析Redis Cluster原理
2021/06/21 Redis
如何vue使用el-table遍历循环表头和表体数据
2022/04/26 Vue.js