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 相关文章推荐
实现 win2003 下 mysql 数据库每天自动备份
Dec 06 PHP
php生成缩略图的类代码
Oct 02 PHP
工厂模式在Zend Framework中应用介绍
Jul 10 PHP
基于PHP遍历数组的方法汇总分析
Jun 08 PHP
PHP 获取文件权限函数介绍
Jul 11 PHP
php快递单号查询接口使用示例
May 05 PHP
php导出csv格式数据并将数字转换成文本的思路以及代码分享
Jun 05 PHP
php实现微信公众平台账号自定义菜单类
Oct 11 PHP
Yii2框架使用计划任务的方法
May 25 PHP
php 数组字符串搜索array_search技巧
Jul 05 PHP
PHP之将POST数据转化为字符串的实现代码
Nov 03 PHP
php打开本地exe程序,js打开本地exe应用程序,并传递相关参数方法
Feb 06 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
【COS正片】蕾姆睡衣cos,纯洁可爱被治愈了 cn名濑弥七
2020/03/02 日漫
php adodb连接mssql解决乱码问题
2009/06/12 PHP
Zend Framework实现具有基本功能的留言本(附demo源码下载)
2016/03/22 PHP
解决在laravel中leftjoin带条件查询没有返回右表为NULL的问题
2019/10/15 PHP
两个Javascript小tip资料
2010/11/23 Javascript
解决jquery的datepicker的本地化以及Today问题
2012/05/23 Javascript
JavaScript中变量提升 Hoisting
2012/07/03 Javascript
用JQuery 判断某个属性是否存在hasAttr的解决方法
2013/04/26 Javascript
使用Js让Html中特殊字符不被转义
2013/11/05 Javascript
jquery获取URL中参数解决中文乱码问题的两种方法
2013/12/18 Javascript
使用AJAX实现Web页面进度条的实例分享
2016/05/06 Javascript
d3.js实现简单的网络拓扑图实例代码
2016/11/06 Javascript
原生js更改css样式的两种方式
2017/03/15 Javascript
vue.js表单验证插件(vee-validate)的使用教程详解
2019/05/23 Javascript
微信小程序如何播放腾讯视频的实现
2019/09/20 Javascript
Vue初始化中的选项合并之initInternalComponent详解
2020/06/11 Javascript
[01:08:48]LGD vs OG 2018国际邀请赛淘汰赛BO3 第三场 8.25
2018/08/29 DOTA
Python命令启动Web服务器实例详解
2017/02/23 Python
Python面向对象之类和对象属性的增删改查操作示例
2018/12/14 Python
python面试题小结附答案实例代码
2019/04/11 Python
Python timer定时器两种常用方法解析
2020/01/20 Python
python数据预处理 :样本分布不均的解决(过采样和欠采样)
2020/02/29 Python
如何在Python 游戏中模拟引力
2020/03/27 Python
python实现输入三角形边长自动作图求面积案例
2020/04/12 Python
Django haystack实现全文搜索代码示例
2020/11/28 Python
python 获取谷歌浏览器保存的密码
2021/01/06 Python
安纳塔拉酒店度假村及水疗官方网站:Anantara Hotel
2016/08/25 全球购物
英国家喻户晓的折扣商场:TK Maxx
2017/05/26 全球购物
毕业生个人求职自荐信
2014/02/26 职场文书
本科生自荐信
2014/06/18 职场文书
学校国庆节活动总结
2015/03/23 职场文书
红色电影观后感
2015/06/18 职场文书
2015国庆66周年宣传语
2015/07/14 职场文书
php中配置文件保存修改操作 如config.php文件的读取修改等操作
2021/05/12 PHP
mybatis中注解与xml配置的对应关系和对比分析
2021/08/04 Java/Android
Python Pygame实战在打砖块游戏的实现
2022/03/17 Python