PHP多线程之Worker-Stackable
PHP多线程之Worker-Stackable · Oct 30, 2013 clicks
PHP的pthreads扩展的文档几乎等同于没有,估计作者也没怎么用心去做这个事。
研究了一下Thread,Worker,Stackable这几个类的用法,全靠一行行地去试代码。。。。
研究了一下Thread,Worker,Stackable这几个类的用法,全靠一行行地去试代码。。。。
网上找了一个例子,基本上也只有这一个,我把网上的代码简化了一下
<?php class MyStackable extends Stackable{ public $id,$name; public function __construct($id){ $this->id = $id; $this->name = 'Stackalbe_'.$id; } public function run(){ $start = time(); $wait = intval(rand(1,5)); sleep($wait); $last = time()-$start; if($this->worker){ $str = sprintf("Running %s in %s costs %d secs.\n",$this->getName(), $this->worker->getName(),$last ); printf($str); $this->worker->setData( $str ); $this->worker->addAttempt(); }else{ printf("faild to get worker \n"); } } public function getName(){ return $this->name; } public function getId(){ return $this->id; } } class MyWorker extends Worker{ protected $id,$name,$_data=[]; public function __construct($id){ $this->name = 'Worker_'.$id; $this->id = $id; $this->attempts = 0; } public function getName(){ return $this->name; } public function addAttempt(){ $this->attempts ++; } public function run(){ printf("running Worker: %s (%lu)\n", $this->getName(), $this->getThreadId()); } public function setData($str){ $this->_data[] = $str; } public function getData(){ return join('',$this->_data); } public function getAttempts(){ return $this->attempts; } } class CPool { public $workers = []; public $status = []; protected $limit = 10; protected $length = 0; public $running = false; public function __construct($size){ $this->limit = $size; } protected function getWorker($no){ $worker = new MyWorker($no); $worker->setData("worker inited \n"); $worker->start(PTHREADS_INHERIT_NONE); return $worker; } public function add(Stackable $stackable){ if ( $this->length < $this->limit ){ printf("add item to stack\n"); $id = $stackable->getId(); $no = $id % 2; if ( empty($this->workers[$no]) ){ $this->workers[$no] = $this->getWorker($no); } if($this->workers[$no]->stack($stackable)){ $this->length ++; return true; }else{ printf("Worker[%d] is full.\n",$no); return false; } }else{ return false; } } public function shutdown(){ foreach($this->workers as $worker){ printf("Worker %s shutdown[%d]\n",$worker->getName() ,$worker->shutdown()); } } public function getAttempts(){ foreach($this->workers as $worker){ printf("%s attempts %d times.\n",$worker->getName(),$worker->getAttempts() ); } } public function getData(){ foreach($this->workers as $worker){ printf("%s 's data is %s \n",$worker->getName(), $worker->getData() ); } } } echo "Start...\n"; $start_time = microtime(1); $pool = new CPool(5); $works = []; for ( $i=0; $i<10; $i++){ $st = new MyStackable( $i ); $works[] = $st;//Notice!!!! $pool->add( $st ); } $pool->shutdown(); $pool->getAttempts(); $pool->getData() ; printf("Finished all in %f seconds.\n",microtime(1)-$start_time);
【参考: https://github.com/krakjoe/pthreads/blob/master/examples/Pooling.php#L33】
注意$works[] = $st;这一行, 我在这里吃了大亏,一般人看来这一行明显是多余的,但是如果少了这行立马就core了。
感觉pthreads的代码没有遵循zend标准,运行起来各种各样的怪问题都会冒出来。
从代码的运行结果可以看到:
1. 多个Worker之间是并行的,每个Worker的Stackable却是按照顺序(其实也并非“顺序”,因为不一定会从第一个Stackable开始运行)一个一个地运行的。
2. Worker中似乎不支持数组,上面代码中的getData,setData方法就没有效果,而把里面的数组操作改成字符串操作之后又能返回期待的内容了。
===============================
PS:据laruence说这个只能玩,不能应用在生产环境。看来多线程的场景还是用Python吧。