多線程實例學(xué)習(xí)鏈接:
http://www.cnblogs.com/jkko123/tag/php%E7%9A%84%E5%A4%9A%E7%BA%BF%E7%A8%8BPthread/
我們可以通過安裝Pthread擴展來讓PHP支持多線程霹崎。
線程尾菇,有時稱為輕量級進程,是程序執(zhí)行的最小單元劳淆。線程是進程中的一個實體沛鸵,是被系統(tǒng)獨立調(diào)度和分派的基本單位缆八,線程自己不擁有系統(tǒng)資源朝刊,它與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創(chuàng)建和撤消另一個線程底哥,同一進程中的多個線程之間可以并發(fā)執(zhí)行。每一個程序都至少有一個線程趾徽,那就是程序本身翰守,通常稱為主線程蜡峰。線程是程序中一個單一的順序控制流程。 在單個程序中同時運行多個線程完成不同的工作载绿,稱為多線程油航。
//實現(xiàn)多線程必須繼承Thread類
class test extends Thread {
public function __construct($arg){
$this->arg = $arg;
}
//當(dāng)調(diào)用start方法時,該對象的run方法中的代碼將在獨立線程中異步執(zhí)行谊囚。
public function run(){
if($this->arg){
printf("Hello %s\n", $this->arg);
}
}
}
$thread = new test("World");
if($thread->start()) {
//join方法的作用是讓當(dāng)前主線程等待該線程執(zhí)行完畢
//確認被join的線程執(zhí)行結(jié)束镰踏,和線程執(zhí)行順序沒關(guān)系奠伪。
//也就是當(dāng)主線程需要子線程的處理結(jié)果,主線程需要等待子線程執(zhí)行完畢
//拿到子線程的結(jié)果含末,然后處理后續(xù)代碼佣盒。
$thread->join();
}
?>
我們把上述代碼修改一下肥惭,看看效果
<?php
class test extends Thread {
public function __construct($arg){
$this->arg = $arg;
}
public function run(){
if($this->arg){
sleep(3);
printf("Hello %s\n", $this->arg);
}
}
}
$thread = new test("World");
$thread->start();
echo "main thread\r\n";
?>
我們直接調(diào)用start方法,而沒有調(diào)用join蜜葱。主線程不會等待牵囤,而是在輸出main thread揭鳞。子線程等待3秒才輸出Hello World野崇。
例1如下:
<?php
class test extends Thread {
private $name = '';
private $res = null;
public function __construct($name, $res){
$this->name = $name;
$this->res = $res;
}
public function run(){
while(!feof($this->res)) {
if(flock($this->res, LOCK_EX)) {
$data = fgets($this->res);
$data = trim($data);
echo "Thread {$this->name} Read {$data} \r\n";
sleep(1);
flock($this->res, LOCK_UN);
}
}
}
}
$fp = fopen('./test.log', 'rb');
$threads[] = new test('a', $fp);
$threads[] = new test('b', $fp);
foreach($threads as $thread) {
$thread->start();
}
foreach($threads as $thread) {
$thread->join();
}
?>
我們通過創(chuàng)建兩個線程a和b來讀取文件test.log中的內(nèi)容乓梨。(*注意,在并發(fā)讀寫文件時脆霎,一定要給文件加鎖睛蛛。這里給文件加上獨占鎖胧谈,如果加共享鎖會出現(xiàn)讀取相同數(shù)據(jù)。)
test.log的內(nèi)容如下:
111111
222222
333333
444444
555555
666666
執(zhí)行結(jié)果如下:
例2如下:
<?php
class Total extends Thread {
public $name = '';
private $total = 0;
private $startNum = 0;
private $endNum = 0;
public function __construct($name, $startNum, $endNum){
$this->name = $name;
$this->startNum = $startNum;
$this->endNum = $endNum;
}
public function run(){
for($ix = $this->startNum; $ix < $this->endNum; ++$ix) {
$this->total += $ix;
}
echo "Thread {$this->name} total: {$this->total} \r\n";
}
public function getTotal() {
return $this->total;
}
}
$num = 10000000;
$threadNum = 10;
$setp = $num / $threadNum;
$startNum = 0;
$startTime = microtime(true);
for($ix = 0; $ix < $threadNum; ++$ix) {
$endNum = $startNum + $setp;
$thread = new Total($ix, $startNum, $endNum);
$thread->start();
$startNum = $endNum;
$threads[] = $thread;
}
$total = 0;
foreach($threads as $thread) {
$thread->join();
$total += $thread->getTotal();
}
$endTime = microtime(true);
$time = $endTime - $startTime;
echo "total : {$total} time : {$time} \r\n";
我們通過創(chuàng)建10個線程,分別計算累加和场仲,而后主線程把10個線程計算的結(jié)果統(tǒng)一相加得到最后結(jié)果渠缕。
我們不使用多線程亦鳞,來計算這累加和遭笋,代碼如下:
<?php
$total = 0;
$startTime = microtime(true);
for($ix = 0; $ix < 10000000; ++$ix) {
$total += $ix;
}
$endTime = microtime(true);
$time = $endTime - $startTime;
echo "total : {$total} time : {$time} \r\n";
我們可以看到使用多線程和不使用瓦呼,得到的結(jié)果是一樣的测暗,但是處理時間,多線程就慢很多。(*主要是線程的創(chuàng)建也是需要資源的挫掏,而且線程之間的相互切換也需要時間尉共,這里的例子主要說明如何把一個問題分配給多個子線程去處理,然后主線程拿到子線程的結(jié)果并處理得到我們需要的結(jié)果弃锐。)