久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      PHP多任務(wù)秒級(jí)定時(shí)器的實(shí)現(xiàn)方法

      描述

      最近在公司部署crontab的時(shí)候,突發(fā)奇想是否可以用PHP去實(shí)現(xiàn)一個(gè)定時(shí)器,顆粒度到秒級(jí)就好,因?yàn)閏rontab最多到分鐘級(jí)別,同時(shí)也調(diào)研了一下用PHP去實(shí)現(xiàn)的定時(shí)器還真不太多,Swoole 擴(kuò)展里面到實(shí)現(xiàn)了一個(gè)毫秒級(jí)的定時(shí)器很高效,但畢竟不是純PHP代碼寫的,所以最后還是考慮用PHP去實(shí)現(xiàn)一個(gè)定時(shí)器類,以供學(xué)習(xí)參考。

      實(shí)現(xiàn)

      在實(shí)現(xiàn)定時(shí)器代碼的時(shí)候,用到了PHP系統(tǒng)自帶的兩個(gè)擴(kuò)展

      Pcntl – 多進(jìn)程擴(kuò)展 :

      主要就是讓PHP可以同時(shí)開啟很多子進(jìn)程,并行的去處理一些任務(wù)。

      Spl – SplMinHeap – 小頂堆

      一個(gè)小頂堆數(shù)據(jù)結(jié)構(gòu),在實(shí)現(xiàn)定時(shí)器的時(shí)候,采用這種結(jié)構(gòu)效率還是不錯(cuò)的,插入、刪除的時(shí)間復(fù)雜度都是 O(logN) ,像 libevent 的定時(shí)器也在 1.4 版本以后采用了這種數(shù)據(jù)結(jié)構(gòu)之前用的是 rbtree,如果要是使用鏈表或者固定的數(shù)組,每次插入、刪除可能都需要重新遍歷或者排序,還是有一定的性能問題的。

      流程

      PHP多任務(wù)秒級(jí)定時(shí)器的實(shí)現(xiàn)方法

      說明

      1、定義定時(shí)器結(jié)構(gòu),有什么參數(shù)之類的.

      2、然后全部注冊(cè)進(jìn)我們的定時(shí)器類 Timer.

      3、調(diào)用定時(shí)器類的monitor方法,開始進(jìn)行監(jiān)聽.

      4、監(jiān)聽過程就是一個(gè)while死循環(huán),不斷的去看時(shí)間堆的堆頂是否到期了,本來考慮每秒循環(huán)看一次,后來一想每秒循環(huán)看一次還是有點(diǎn)問題,如果正好在我們sleep(1)的時(shí)候定時(shí)器有到期的了,那我們就不能馬上去精準(zhǔn)執(zhí)行,可能會(huì)有延時(shí)的風(fēng)險(xiǎn),所以還是采用 usleep(1000) 毫秒級(jí)的去看并且也可以將進(jìn)程掛起減輕 CPU 負(fù)載.

      代碼

      /*** * Class Timer */ class Timer extends SplMinHeap {   /**   * 比較根節(jié)點(diǎn)和新插入節(jié)點(diǎn)大小   * @param mixed $value1   * @param mixed $value2   * @return int   */   protected function compare($value1, $value2)   {     if ($value1['timeout'] > $value2['timeout']) {       return -1;     }     if ($value1['timeout'] < $value2['timeout']) {       return 1;     }     return 0;   }   /**   * 插入節(jié)點(diǎn)   * @param mixed $value   */   public function insert($value)   {     $value['timeout'] = time() + $value['expire'];     parent::insert($value);   }   /**   * 監(jiān)聽   * @param bool $debug   */   public function monitor($debug = false)   {     while (!$this->isEmpty()) {       $this->exec($debug);       usleep(1000);     }   }   /**   * 執(zhí)行   * @param $debug   */   private function exec($debug)   {     $hit = 0;     $t1  = microtime(true);     while (!$this->isEmpty()) {       $node = $this->top();       if ($node['timeout'] <= time()) {         //出堆或入堆         $node['repeat'] ? $this->insert($this->extract()) : $this->extract();         $hit = 1;         //開啟子進(jìn)程         if (pcntl_fork() == 0) {           empty($node['action']) ? '' : call_user_func($node['action']);           exit(0);         }         //忽略子進(jìn)程,子進(jìn)程退出由系統(tǒng)回收         pcntl_signal(SIGCLD, SIG_IGN);       } else {         break;       }     }     $t2 = microtime(true);     echo ($debug && $hit) ? '時(shí)間堆 - 調(diào)整耗時(shí): ' . round($t2 - $t1, 3) . "秒rn" : '';   } }

      實(shí)例

      $timer = new Timer(); //注冊(cè) - 3s - 重復(fù)觸發(fā) $timer->insert(array('expire' => 3, 'repeat' => true, 'action' => function(){   echo '3秒 - 重復(fù) - hello world' . "rn"; })); //注冊(cè) - 3s - 重復(fù)觸發(fā) $timer->insert(array('expire' => 3, 'repeat' => true, 'action' => function(){   echo '3秒 - 重復(fù) - gogo' . "rn"; })); //注冊(cè) - 6s - 觸發(fā)一次 $timer->insert(array('expire' => 6, 'repeat' => false, 'action' => function(){   echo '6秒 - 一次 - hello xxxx' . "rn"; })); //監(jiān)聽 $timer->monitor(false);

      執(zhí)行結(jié)果

      PHP多任務(wù)秒級(jí)定時(shí)器的實(shí)現(xiàn)方法

      也測(cè)試過比較極端的情況,同時(shí)1000個(gè)定時(shí)器1s全部到期,時(shí)間堆全部調(diào)整完僅需 0.126s 這是沒問題的,但是每調(diào)整完一個(gè)定時(shí)器就需要去開啟一個(gè)子進(jìn)程,這塊可能比較耗時(shí)了,有可能1s處理不完這1000個(gè),就會(huì)影響下次監(jiān)聽繼續(xù)觸發(fā),但是不開啟子進(jìn)程,比如直接執(zhí)行應(yīng)該還是可以處理完的。。。。當(dāng)然肯定有更好的方法,目前只能想到這樣。

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)