设计动量论坛's Archiver

sogood 发表于 2007-3-24 11:05

php实现多线程技术

我们知道PHP本身是不支持多线程的, 但是我们的WEB服务器是支持多线程的.
*`[.dhh\*? 5Gr8Au_)\ x

fAJ(a~ fPG 也就是说可以同时让多人一起访问. 这也是我在PHP中实现多线程的基础.
+N X7m:a*VU(Y
V4X8@@4n T,?/k'~]'?
o e il CbL+W 假设我们现在运行的是a.PHP这个文件. 但是我在程序中又请求WEB服务器运行另一个b.PHP ]6b?We YkR'y

"@le-V f;D#t ,~l:T E%@i N!x
那么这两个文件将是同时执行的. c,Y&uP9p/wo

!AB;bt V2g N8xf7y$v
.d~8Jr'y (PS: 一个链接请求发送之后, WEB服务器就会执行它, 而不管客户端是否已经退出)
:L{!?S9g CxN
-A6x8dTR B q,IU1L `HtR
有些时候, 我们想运行的不是另一个文件, 而是本文件中的一部分代码.该怎么办呢?
!} Jv3A2O N({{ |6Y2u'T

Kd0^)j&MG(z K C 其实可是通过参数来控制a.PHP来运行哪一段程序. gnd'e,f;~g/u

@4X%w2B*C8yr4B;j
%GGn:e:w1N1PR0k%Yo~ 下面看一个例子: VCL_[9f EG(W
9hQ Q!L S#p$b$m _1`

w1t9O4A7]$F%]@Kj //a.PHP
-M%pi#b ?9YP f 4W*N mZ:^ }3oX
B"m!W8L-d^"A!BA
PHP代码:--------------------------------------------------------------------------------
QX8a\\i!e-^4w m&Ek&MY;fe^P
$n2[s&Z~h
<?PHP
'F"f5?6G@.}N6E@!B
(z ^#LTK7}.n*_ga function runThread() ,`jx6p_)j W

!u1\ Op}qE {
,?ti+| [\sE
N!N Ld"d4``` Z,[ $fp = fsockopen(localhost, 80, $errno, $errmsg);
4d2YR nmnV ?-I
5\:Y Mc m 0?b1DN v%}^9F
fputs($fp, "GET /a.PHP?act=b_an n,K'S&Y'w3e$]6|
4Xu2hd_
"); //这里的第二个参数是HTTP协议中规定的请求头 1CZRE0qH

5]9m_%_}-} //不明白的请看RFC中的定义
ZH S Zrvn Uuo
%d9Em4DjG:uh
:J f!c\eHhi&xm fclose($fp);
KM;F-`D x-?Pt I$F%A
*GbZ cs\o:r } /dq G}E
w-H"d#rm2YD Y\

p*OJ7vz` function a() "O*h _*oG e\fjc j-K*Q
kZ7EUZqO
{ m1G R*|K3j
*Emi:e9M%D
$fp = fopen(result_a.log, w);
4O(D1CwkO
7o p9jim U2{)P fputs($fp, Set in . Date(h:i:s, time()) . (double)microtime() . " m P\e*B CF0H
"); $d`3?,\ r
(U*u&X p'J)glfp_

O"`"E0tU.d3] fclose($fp);
2Tb1Gdz#z&K
,B'e]eIUr~ } Jt W uk6l(UJx
g \r#gFO i,z2q
b9v*\:A w p9p0c a
function b() %i7l"pa)`&LE?S F

gq,|\[3WJ8vKZ[` {
q5E-B C%s8Nm
,Y9gf(da2}*vF N*J $fp = fopen(result_b.log, w); h lT%TrA4BP ]

,]7T:QruM:dr O fputs($fp, Set in . Date(h:i:s, time()) . (double)microtime() . "
hr1z&HP7OM#n7X3M ");
Y6q5uc2VZ w+})B6m;JF

7HVqkPPT'q fclose($fp); P7B%PHnp;o

8v_z6l)~KV{)C!W] }
4^6])B'Qi2`,l0m"Jk,R
^#]%c|0r v
6y$F6a i m#c3Rn if(!isset($_GET[act])) $_GET[act] = a;
^|1pcm#U-Z{ `v$c8[_b}

`%ni1i6gP if($_GET[act] == a)
DT+n+Oy-y6[J$| Z
3[&r3L.DV E s@9I {
]!f#D+I3cb9l +F,l}}-H*v7{
runThread();
8GaD{%gM
(P3V `$a GI a(); g8eiS O^

{ O|&yq XS0j:L } GKA7?VH!c H`

K*u&[ j%V,B.a b else if($_GET[act] == b) b(); 1_y,T!gzW3wZ/bdk

Mmj`D&ww ?>
.Xy+t,HcRx h0qL~u
z*{ B;v+v fu]q%z`zS
--------------------------------------------------------------------------------
B/Z n%p:hp.uX }:{ {CTAhrfY^

8R G2rx \'{
0Rg)X2u^2CF~#T 打开result_a.log 和 result_b.log 比较一下两个文件的中访问的时间. 大家会发现, 这两个的确是在不同线程中运行的. *K va ]/A)D9xu
0k2Qq$W d&of"Z
有些时间完全一样.
+v ~,x.B4?#Cy8R 2kK1Xe @a8s&P

;A)}5}l],Smy 上面只是一个简单的例子, 大家可以改进成其它形式.
o2o1ib:g6d2B;` UF !bTG)qc(mp

'?2^'r!m6]+f|4i qG F:QJ_wp
既然PHP中也能多线程了, 那么问题也来了, 那就是同步的问题. 我们知道 PHP本身是不支持多线程的. 所以更不会有什么像 6U@ K(FG%xD

!N9qzfO
I:|"O6jk.G5T%Gh$w Java 中synchronize的方法了. 那我们该如何做呢.
!p!ew"v ~$J tV
Xg{&P+ne baWT!}.vf
1. 尽量不访问同一个资源. 以避免冲突. 但是可以同时像数据库操作. 因为数据库是支持并发操作的. 所以在多线程的PHP中 dm U5tWs`!o0R,O
U:gy/\z1B

+rSH){I:Y:A 不要向同一个文件中写入数据. 如果必须要写的话, 用别的方法进行同步.. 如调用 flock对文件进行加锁等. 或建立临时文件
v j2~)P.a;i1C Mr'`%lL'O5kT
u*hr0f|&}mT
并在另外的线程中等待这个文件的消失 while(file_exits(xxx)); 这样就等于这个临时文件存在时, 表示其实线程正在操作 0L?#a7D8f'D-mDN/]`!`

I!w `%fr
zfp2q ^M2d 如果没有了这个文件, 说明其它线程已经释放了这个. %b~8g0t&Wb UBn

J\"RY)Y(BJ)B
TE?0d8sa 2. 尽量不要从runThread在执行fputs后取这个socket中读取数据. 因为要实现多线程, 需要的用非阻塞模式. 即在像fgets这
N deMY,Fzz &he,WwS,Z#rc:U

`7d(X.IkS7o5Mvj2l5L 样的函数时立即返回.. 所以读写数据就会出问题. 如果使用阻塞模式的话, 程序就不算是多线程了. 他要等上面的返回才执行
+} il(}R K
iEp;o%@3U ~M2~|$\ 0L"cVB,Cya;N|
下面的程序. 所以如果需要交换数据最后利用外面文件或数据中完成. 实在想要的话就用socket_set_nonblock($fp) 来实现.
7l$ot-F)H N-Dt4k r/Q

3?*S LBA+Hh_J&En K
0["tYVpi{0p3J 说了这么多, 倒底这个有没有实际的意义呢? 在什么时候需要这种用这种方法呢 ?
-Y.c_XO RG SADL/T _5f
(|EaXBB$f
答案是肯定的. 大家知道. 在一个不断读取网络资源的应用中, 网络的速度是瓶颈. 如果采多这种形式就可以同时以多个线程对不同的页面进行读取.

页: [1]

Powered by Discuz! Archiver 7.0.0  © 2001-2009 Comsenz Inc.