当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP 进程池与轮询调度算法实现多任务的示例代码

发布:smiling 来源: PHP粉丝网  添加日期:2022-01-24 14:07:53 浏览: 评论:0 

这篇文章主要介绍了PHP 进程池与轮询调度算法实现多任务的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。

phper 请了解进程调度策略,CPU 时间片,进程控制【创建,销毁,回收,进程信号】与及进程运行流程和基本的进程组,信号中断原理,以及进程之间的关系。

关于进程的更多内容可参考本人前面撸过的文章或是百度了解。

进程的通信:

匿名管道,命名管道,消息队列,内存共享,socketpair 请自行撸代码测试哦

进程的调度算法:

轮询,随机分发,计分板等策略或是搞个优先极或是队列,或是堆栈等基本的算法【自己去发挥哦】

进程池:

撸过 tcp 的话应该知道要能处理多个客户端,就得用 IO 复用技术【事件多路分发器】或是多进程以及多线程,每来一个客户端就 fork 一个进程或是线程,那样的话上下文切换成本特别高,所以咱们先创建好一组进程【进程池】,等客户端连接上来的时候,通过某种算法【我们用的轮询】来选择某个进程投递任务来干活,这样的话就不用创建又销毁来回折腾了,提升它的效率。下面是 PHP 代码版本的实现

  1. <?php 
  2. /** 
  3.  * Created by PhpStorm. 
  4.  * User: 1655664358@qq.com 
  5.  * Date: 2019/1/12 
  6.  * Time: 16:18 
  7.  */ 
  8.  
  9. $flag = 1; 
  10.  
  11. class process 
  12.  public $pid
  13.  public $name
  14.  public $file
  15.  public $num
  16. class instance 
  17.  public $processIdx
  18.  public $proc = []; 
  19.  public $processNum
  20. function sigHandler($sigNo
  21.  global $flag
  22.  $flag = 0; 
  23.  echo "信号中断处理".PHP_EOL; 
  24. function processPool(instance &$instance,$num
  25.  
  26.  if (!$instance||$num==0){ 
  27.   fprintf(STDERR,"%s","参数错误"); 
  28.   return 1; 
  29.  } 
  30.  $instance->processIdx = 0; 
  31.  $instance->processNum = $num
  32.  
  33.  pcntl_signal(SIGINT,'sigHandler'); 
  34.  pcntl_signal(SIGTERM,'sigHandler'); 
  35.  
  36.  $process = new process(); 
  37.  for ($i=1;$i<=$num;$i++){ 
  38.   $instance->proc[$i] = clone $process
  39.   $instance->proc[$i]->file = $i
  40.   $instance->proc[$i]->pid = pcntl_fork(); 
  41.   $instance->processIdx = $i
  42.   if ($instance->proc[$i]->pid<0){ 
  43.    exit("进程创建失败"); 
  44.   } 
  45.   else if ($instance->proc[$i]->pid>0){ 
  46.    //nothing 
  47.    continue
  48.   }else
  49.  
  50.    worker($instance); 
  51.   } 
  52.  } 
  53.  master($instance); 
  54.  $exitProcess= []; 
  55.  while (1){ 
  56.   for ($i=1;$i<=$num;$i++){ 
  57.   //非阻塞方式回收子进程 
  58.    pcntl_waitpid($instance->proc[$i]->pid,$status,WNOHANG); 
  59.    if ($status){ 
  60.     $exitProcess[] = $instance->proc[$i]->pid; 
  61.     fwrite(STDOUT,"worker#".$instance->proc[$i]->pid."-".$status,30); 
  62.    } 
  63.   } 
  64.   if (count($exitProcess)==$instance->processNum){ 
  65.    exit(0); 
  66.   } 
  67.   usleep(1000); 
  68.  
  69.  } 
  70.  
  71. //简单的轮询算法 自己可以用队列,随机,链表,栈链,二叉树啥的折腾 
  72. function roundRobin(&$instance,$roll
  73.  /** @var instance $instance */ 
  74.  return $instance->proc[$roll%$instance->processNum+1]; 
  75.  
  76. function master(&$instance
  77.  
  78.  /** @var instance $instance */ 
  79.  fprintf(STDOUT,"master 进程 %d\n",$instance->processIdx); 
  80.  global $flag
  81.  $roll = 0; 
  82.  while ($flag){ 
  83.   pcntl_signal_dispatch(); 
  84.   /** @var process $process */ 
  85.   $process = roundRobin($instance,$roll++); 
  86.   echo "轮询的进程:".$process->pid.PHP_EOL; 
  87.   $file = $process->file; 
  88.   posix_mkfifo($file,0666); 
  89.   $fd = fopen($file,"w"); 
  90.   fwrite($fd,"hi",2); 
  91.   sleep(1); 
  92.  
  93.  } 
  94.  for ($i=1;$i<=$instance->processNum;$i++){ 
  95.   posix_kill($instance->proc[$i]->pid,9); 
  96.  } 
  97.  fprintf(STDOUT,"master shutdown %d\n",$instance->processIdx); 
  98. function getProcess(&$instance
  99.  /** @var instance $instance */ 
  100.  return $instance->proc[$instance->processIdx]; 
  101. function worker(&$instance
  102.  /** @var process $process */ 
  103.  $process = getProcess($instance); 
  104.  while (1){ 
  105.   $file = $process->file; 
  106.   posix_mkfifo($file,0666); 
  107.   $fd = fopen($file,"r"); 
  108.   $content = fread($fd,10); 
  109.   fprintf(STDOUT,"worker#%d读取的内容:%s file=%d\n",posix_getpid(),$content,$file); 
  110.  } 
  111.  exit(0); 
  112.  
  113. $instance = new instance(); 
  114. processPool($instance,5); 

效果

PHP进程池 PHP轮询调度

Tags: PHP进程池 PHP轮询调度

分享到: