[转]通俗易懂的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 ...
随机推荐
- [图文][提供可行性脚本] CentOS 7 Fencing+Pacemaker三节点搭建高可用集群
实验说明: 实验环境: 宿主机系统 :Fedora 28 WorkStation 虚拟机管理器 :Virt-Manager 1.5.1 虚拟机配置 :ha1 CentOS 7.2 1511 ...
- 蓝牙学习(2)USB Adapter
主要分析一下蓝牙USB Adapter使用USB接口传输HCI包的实现及过程. 参照上面的Bluetooth core system architecture图, 蓝牙USB Adapter作为Blu ...
- python logging with yaml
Recently, I was made a service which can provide a simple way to get best model. so, i spent lot of ...
- stm32L011F3——串口实例
/* STM32L0xx HAL library initialization: - Configure the Flash prefetch, Flash preread and Buffer ca ...
- Sequence Models
Sequence Models This is the fifth and final course of the deep learning specialization at Coursera w ...
- Leetcode 392.判断子序列
判断子序列 给定字符串 s 和 t ,判断 s 是否为 t 的子序列. 你可以认为 s 和 t 中仅包含英文小写字母.字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 ...
- 九度oj 题目1179:阶乘
题目描述: 输入n, 求y1=1!+3!+...m!(m是小于等于n的最大奇数)y2=2!+4!+...p!(p是小于等于n的最大偶数). 输入: 每组输入包括1个整数:n 输出: 可能有多组测试数据 ...
- 九度oj 题目1112:拦截导弹
题目描述: 某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导 ...
- 【Luogu】P1593因子和(唯一分解定理,约数和公式)
题目链接 首先介绍两个定理. 整数唯一分解定理:任意正整数都有且只有一种方式写出素数因子的乘积表达式. \(A=(p1k1 p2k2 ...... pnkn \) 求这些因子的代码如下 ;i*i< ...
- 怎么创建SpringBoot项目
上述中讲到了怎么创建SpringBoot项目,那么现在就来介绍下SpringBoot配置文件的两种格式yml和properties 首先呢发上一份application.properties 在放上一 ...