原文: https://www.w3cschool.cn/php/php-thread.html

------------------------------------------------------------------

通俗易懂的php多线程解决方案

由 youj 创建,Carrie 最后一次修改 2016-12-01

我们在做项目的时候,有些需求,特别是数据的响应处理需要花费大量的时间,由于php是一个短生命周期的脚本语言,到了默认的30秒,php的数据处理还没完成,php的生命周期就结束了。这时需要使用异步并发处理策略,也就是说,一次php调用可以发出的多个请求,这些请求不是按照顺序执行,而是可以异步并发执行的,一些请求用于在后台处理数据,一些请求用于接受后台响应状态,根据状态,与用户做一些简单的交互。但是问题来了,我们都知道php本身是不支持多线程的,那么应该怎么实现php的多线程呢?

一、php模拟实现多线程的三种方法

1、linux下的php多线程

下面所讲的东西是源自php的pcntl_fork函数.因为这个函数依赖操作系统fork的实现,所以本文所讲的东西只适用于linux/unix。那么先看看这个函数的用法吧.php手册上是这么说的:

<?php
$pid = pcntl_fork();
if ($pid == -1) {
die('could not fork');
} else if ($pid) {
// we are the parent
pcntl_wait($status); //Protect against Zombie children
} else {
// we are the child
}
?>

通过pcntl_fork创建一个子进程,如果返回值是-1的话,那么说明子进程创建失败.创建成功的进程id会返回给父进程,0返回给子进程.不好理解吧,所以应该这样写:

<?php
$pid = pcntl_fork();
if($pid == -1){
//创建失败咱就退出呗,没啥好说的
die('could not fork');
}
else{
if($pid){
//从这里开始写的代码是父进程的,因为写的是系统程序,记得退出的时候给个返回值
exit(0);
}
else{
//从这里开始写的代码都是在新的进程里执行的,同样正常退出的话,最好也给一个返回值
exit(0);
}
}
?>

这样一改好理解多了,如果你父进程希望知道子进程正常退出的话,可以加上前面的pcntl_wait。

2.通过stream_socket_client 方式

function sendStream() {
$english_format_number = number_format($number, 4, '.', ''); echo $english_format_number;
exit();
$timeout = 10;
$result = array();
$sockets = array();
$convenient_read_block = 8192;
$host = "test.local.com";
$sql = "select waybill_id,order_id from xm_waybill where status>40 order by update_time desc limit 1 ";
$data = Yii::app()->db->createCommand($sql)->queryAll();
$id = 0; foreach ($data as $k => $v) {
if ($k % 2 == 0) {
$send_data[$k]['body'] = NoticeOrder::getSendData($v['waybill_id']); } else {
$send_data[$k]['body'] = array($v['order_id'] => array('extra' => 16));
}
$data = json_encode($send_data[$k]['body']);
$s = stream_socket_client($host . ":80", $errno, $errstr, $timeout, STREAM_CLIENT_ASYNC_CONNECT | STREAM_CLIENT_CONNECT);
if ($s) {
$sockets[$id++] = $s;
$http_message = "GET /php/test.php?data=" . $data . " HTTP/1.0\r\nHost:" . $host . "\r\n\r\n";
fwrite($s, $http_message);
} else {
echo "Stream " . $id . " failed to open correctly.";
}
} while (count($sockets)) { $read = $sockets; stream_select($read, $w = null, $e = null, $timeout);
if (count($read)) {
/* stream_select generally shuffles $read, so we need to
compute from which socket(s) we're reading. */
foreach ($read as $r) { $id = array_search($r, $sockets);
$data = fread($r, $convenient_read_block);
if (strlen($data) == 0) {
echo "Stream " . $id . " closes at " . date('h:i:s') . ".<br> ";
fclose($r);
unset($sockets[$id]);
} else {
$result[$id] = $data;
}
}
} else {
/* A time-out means that *all* streams have failed
to receive a response. */
echo "Time-out!\n";
break;
}
}
print_r($result); }

3、通过多进程代替多线程

function daemon($func_name,$args,$number){
while(true){
$pid=pcntl_fork();
if($pid==-1){
echo "fork process fail";
exit();
}elseif($pid){//创建的子进程 static $num=0;
$num++;
if($num>=$number){
//当进程数量达到一定数量时候,就对子进程进行回收。
pcntl_wait($status); $num--;
}
}else{ //为0 则代表是子进程创建的,则直接进入工作状态 if(function_exists($func_name)){
while (true) {
$ppid=posix_getpid();
var_dump($ppid);
call_user_func_array($func_name,$args);
sleep(2);
}
}else{
echo "function is not exists";
}
exit();
}
}
}
function worker($args){
//do something }
daemon('worker',array(1),2);

二、真正实现php多线程的方法

php真正的多线程实现方式,通过安装php的扩展 pthread 可以做到。

 
但是这个下载的是 版本3 也就是php 7 才能用的,我们需要使的是 版本2
 
然后刷新的页面如下,拖到最底部:

 

下一页找到版本2的

下载下来,这个v2 才是php5才可以使用的

下载下来,安装:

或者,您直接这样下载:

cd /tools
wget https://github.com/krakjoe/pthreads/archive/v2.0.10.zip
unzip v2.0.10.zip
cd pthreads-2.0.10
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make
make install

注意:您的php 在编译的时候需要开启 –enable-maintainer-zts

./configure --prefix=/usr/local/php --disable-fileinfo   --enable-fpm --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --with-openssl --with-zlib --with-curl --enable-ftp --with-gd --with-xmlrpc  --with-jpeg-dir --with-png-dir --with-freetype-dir --enable-gd-native-ttf --enable-mbstring --with-mcrypt=/usr/local/libmcrypt --enable-zip --with-mysql=/usr/local/mysql --without-pear --enable-maintainer-zts
vim /etc/php.ini
添加
extension=pthreads.so
重启php
/etc/init.d/php-fpm restart

[转]通俗易懂的php多线程解决方案的更多相关文章

  1. 通俗易懂的php多线程解决方案

    我们在做项目的时候,有些需求,特别是数据的响应处理需要花费大量的时间,由于php是一个短生命周期的脚本语言,到了默认的30秒,php的数据处理还没完成,php的生命周期就结束了.这时需要使用异步并发处 ...

  2. lua多线程解决方案

    直观的讲:lua并不支持多线程,lua语言本身具有携程功能,但携程仅仅是一种中继器. lua多线程的目的:有并发需求时,共享一些数据. 例如使用lua写一个并发服务器.用户登陆之后,用户数据储存在lu ...

  3. 一种优化操作list、数组的多线程解决方案。

    这几天接触到了一些操作list的功能,由于list太长,加上每条数据的处理时间,导致性能下降,正好利用学来的多线程知识和网上的资料结合实践一番,写出了一个通用类如下. /** * 操作数组的线程 * ...

  4. iOS 多线程讲解2

    1.GCD其他方法 1.GCD应用 单例模式 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@&qu ...

  5. 多线程NSOperation

      NSOperation(经常使用): 1.为什么会有NSOperation?弥补gcd的一些问题:1)下载为例子:如果gcd放到队列中的block操作面对网络有问题,block之外无法取消bloc ...

  6. iOS多线程开发之NSOperation - 快上车,没时间解释了!

    一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...

  7. 深入理解javascript异步编程障眼法&&h5 web worker实现多线程

    0.从一道题说起 var t = true; setTimeout(function(){ t = false; }, 1000); while(t){ } alert('end'); 1 2 3 4 ...

  8. iOS多线程编程--NSOperation(转)

    这篇文章写得非常不错,基础用法都涉及到了,我把文章提到的例子都写到了demo里面, 原文地址: iOS多线程--彻底学会多线程之『NSOperation』 demo下载:https://github. ...

  9. iOS 多线程 NSOperation、NSOperationQueue

    1. NSOperation.NSOperationQueue 简介 NSOperation.NSOperationQueue 是苹果提供给我们的一套多线程解决方案.实际上 NSOperation.N ...

随机推荐

  1. UNIX环境C语言进程通信

    一.信号管理 1.函数signal signal函数是UNIX系统信号机制最简单的接口 #include <signal.h> typedef void (*sighandler_t)(i ...

  2. Ubuntu18.04 无法解析域名

    解决方法: 首先先输入以下4条命令 1. sudo lshw -numeric -class network2. sudo ifconfig -a3. sudo route -nv4. sudo dh ...

  3. (原)剑指offer跳台阶和矩形覆盖

    跳台阶 时间限制:1秒空间限制:32768K 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法.   分析同样为斐波那契数列边形这样的题肯定有公式 设 ...

  4. GYM 101350 G

    G. Snake Rana time limit per test 4.0 s memory limit per test 256 MB input standard input output sta ...

  5. MIP经典问题:旅行商问题 (traveling salesman problem)

    *本文主要记录和分享学习到的知识,算不上原创. *参考文献见链接. 旅行商问题.背包问题都是0-1规划问题中最为经典的问题. 通常来说,当我们学习并熟悉一种求解混合整数问题的技巧时,可以用这种技巧来求 ...

  6. linux查找和替换命令

    http://blog.csdn.net/imyang2007/article/details/8105499 命令的东西应该多练,熟能生巧.

  7. loj2002 「SDOI2017」序列计数

    水题 #include <iostream> #include <cstring> #include <cstdio> using namespace std; t ...

  8. 【LeetCode】Count and Say(报数)

    这道题是LeetCode里的第38道题. 题目要求: 报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数.其前五项如下: 1. 1 2. 11 3. 21 4. 1211 5. 111 ...

  9. POJ-2002 Squares,哈希模板+数学公式!

                                                           Squares 题意:二维坐标轴给出n个点求有多少个正方形. 要是平时做比赛的话毫无疑问会 ...

  10. 九度oj 题目1367:二叉搜索树的后序遍历序列

    题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 输入: 每个测试案例包括2行: 第一行为1个整数 ...