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 相关文章推荐
用ADODB来让PHP操作ACCESS数据库的方法
Dec 31 PHP
PHP中基本符号及使用方法
Mar 23 PHP
第三章 php操作符与控制结构代码
Dec 30 PHP
PHP面向对象学习笔记之二 生成对象的设计模式
Oct 06 PHP
基于php常用正则表达式的整理汇总
Jun 08 PHP
PHP 如何利用phpexcel导入数据库
Aug 24 PHP
php实现的一个很好用HTML解析器类可用于采集数据
Sep 23 PHP
Codeigniter注册登录代码示例
Jun 12 PHP
Laravel框架路由配置总结、设置技巧大全
Sep 03 PHP
10个简化PHP开发的工具
Dec 25 PHP
CI框架AR操作(数组形式)实现插入多条sql数据的方法
May 18 PHP
PHP观察者模式实例分析【对比JS观察者模式】
May 22 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 var_dump遍历对象属性的函数与应用代码
2010/06/04 PHP
php中使用preg_replace函数匹配图片并加上链接的方法
2013/02/06 PHP
php ctype函数中文翻译和示例
2014/03/21 PHP
PHP文件上传处理案例分析
2016/10/15 PHP
PHP实现的登录,注册及密码修改功能分析
2016/11/25 PHP
PHP PDOStatement::setFetchMode讲解
2019/02/03 PHP
laravel 5.3 单用户登录简单实现方法
2019/10/14 PHP
ExtJS 工具栏 分页事件参数
2010/03/05 Javascript
一个简单的网站访问JS计数器 刷新1次加1次访问
2012/09/20 Javascript
jQuery实现仿腾讯微博滑出效果报告每日天气的方法
2015/05/11 Javascript
javascript闭包(Closure)用法实例简析
2015/11/30 Javascript
谷歌Chrome浏览器扩展程序开发小记
2016/01/06 Javascript
js模仿java的Map集合详解
2016/01/06 Javascript
javascript基础知识讲解
2017/01/11 Javascript
vue.js指令v-model使用方法
2017/03/20 Javascript
js实现随机点名系统(实例讲解)
2017/10/18 Javascript
webpack中CommonsChunkPlugin详细教程(小结)
2017/11/09 Javascript
JS实现520 表白简单代码
2018/05/21 Javascript
搭建Vue从Vue-cli到router路由护卫的实现
2019/11/14 Javascript
vuex存取值和映射函数使用说明
2020/07/24 Javascript
[06:36]吞吞映像top1
2014/06/20 DOTA
python 遍历目录(包括子目录)下所有文件的实例
2018/07/11 Python
详解python uiautomator2 watcher的使用方法
2019/09/09 Python
python selenium实现发送带附件的邮件代码实例
2019/12/10 Python
Python jieba库分词模式实例用法
2021/01/13 Python
CSS3 按钮边框动画的实现
2020/11/12 HTML / CSS
html5简介及新增功能介绍
2020/05/18 HTML / CSS
如何查看浏览器对html5的支持情况
2020/12/15 HTML / CSS
三星印度官网:Samsung印度
2019/08/03 全球购物
马来西亚在线健康商店:Medipal Malaysia
2020/04/13 全球购物
2014年大学生党员自我评议
2014/09/22 职场文书
幼儿园教师岗位职责
2015/04/02 职场文书
大学生奶茶店创业计划书
2019/06/25 职场文书
关于企业的执行力标语大全
2020/01/06 职场文书
深度学习tensorflow基础mnist
2021/04/14 Python
html+css实现赛博朋克风格按钮
2021/05/26 HTML / CSS