[转]通俗易懂的php多线程解决方案
原文: https://www.w3cschool.cn/php/php-thread.html
------------------------------------------------------------------
通俗易懂的php多线程解决方案
我们在做项目的时候,有些需求,特别是数据的响应处理需要花费大量的时间,由于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多线程的方法
下一页找到版本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多线程解决方案的更多相关文章
- 通俗易懂的php多线程解决方案
我们在做项目的时候,有些需求,特别是数据的响应处理需要花费大量的时间,由于php是一个短生命周期的脚本语言,到了默认的30秒,php的数据处理还没完成,php的生命周期就结束了.这时需要使用异步并发处 ...
- lua多线程解决方案
直观的讲:lua并不支持多线程,lua语言本身具有携程功能,但携程仅仅是一种中继器. lua多线程的目的:有并发需求时,共享一些数据. 例如使用lua写一个并发服务器.用户登陆之后,用户数据储存在lu ...
- 一种优化操作list、数组的多线程解决方案。
这几天接触到了一些操作list的功能,由于list太长,加上每条数据的处理时间,导致性能下降,正好利用学来的多线程知识和网上的资料结合实践一番,写出了一个通用类如下. /** * 操作数组的线程 * ...
- iOS 多线程讲解2
1.GCD其他方法 1.GCD应用 单例模式 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@&qu ...
- 多线程NSOperation
NSOperation(经常使用): 1.为什么会有NSOperation?弥补gcd的一些问题:1)下载为例子:如果gcd放到队列中的block操作面对网络有问题,block之外无法取消bloc ...
- iOS多线程开发之NSOperation - 快上车,没时间解释了!
一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...
- 深入理解javascript异步编程障眼法&&h5 web worker实现多线程
0.从一道题说起 var t = true; setTimeout(function(){ t = false; }, 1000); while(t){ } alert('end'); 1 2 3 4 ...
- iOS多线程编程--NSOperation(转)
这篇文章写得非常不错,基础用法都涉及到了,我把文章提到的例子都写到了demo里面, 原文地址: iOS多线程--彻底学会多线程之『NSOperation』 demo下载:https://github. ...
- iOS 多线程 NSOperation、NSOperationQueue
1. NSOperation.NSOperationQueue 简介 NSOperation.NSOperationQueue 是苹果提供给我们的一套多线程解决方案.实际上 NSOperation.N ...
随机推荐
- UNIX环境C语言进程通信
一.信号管理 1.函数signal signal函数是UNIX系统信号机制最简单的接口 #include <signal.h> typedef void (*sighandler_t)(i ...
- Ubuntu18.04 无法解析域名
解决方法: 首先先输入以下4条命令 1. sudo lshw -numeric -class network2. sudo ifconfig -a3. sudo route -nv4. sudo dh ...
- (原)剑指offer跳台阶和矩形覆盖
跳台阶 时间限制:1秒空间限制:32768K 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 分析同样为斐波那契数列边形这样的题肯定有公式 设 ...
- GYM 101350 G
G. Snake Rana time limit per test 4.0 s memory limit per test 256 MB input standard input output sta ...
- MIP经典问题:旅行商问题 (traveling salesman problem)
*本文主要记录和分享学习到的知识,算不上原创. *参考文献见链接. 旅行商问题.背包问题都是0-1规划问题中最为经典的问题. 通常来说,当我们学习并熟悉一种求解混合整数问题的技巧时,可以用这种技巧来求 ...
- linux查找和替换命令
http://blog.csdn.net/imyang2007/article/details/8105499 命令的东西应该多练,熟能生巧.
- loj2002 「SDOI2017」序列计数
水题 #include <iostream> #include <cstring> #include <cstdio> using namespace std; t ...
- 【LeetCode】Count and Say(报数)
这道题是LeetCode里的第38道题. 题目要求: 报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数.其前五项如下: 1. 1 2. 11 3. 21 4. 1211 5. 111 ...
- POJ-2002 Squares,哈希模板+数学公式!
Squares 题意:二维坐标轴给出n个点求有多少个正方形. 要是平时做比赛的话毫无疑问会 ...
- 九度oj 题目1367:二叉搜索树的后序遍历序列
题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 输入: 每个测试案例包括2行: 第一行为1个整数 ...