Heim  >  Artikel  >  Backend-Entwicklung  >  Implementierungsmethode des PHP-Multitasking-Timers der zweiten Ebene

Implementierungsmethode des PHP-Multitasking-Timers der zweiten Ebene

不言
不言Original
2018-06-01 09:56:481663Durchsuche

Dieser Artikel stellt hauptsächlich die Implementierungsmethode des PHP-Multitasking-Timers der zweiten Ebene vor. Er ist sehr gut und hat einen gewissen Referenzwert. Freunde in Not können sich auf die

Beschreibung beziehen

Als ich kürzlich Crontab in meinem Unternehmen einsetzte, dachte ich plötzlich darüber nach, ob ich PHP verwenden könnte, um einen Timer zu implementieren. Die Granularität würde bis zur zweiten Ebene reichen, da Crontab erreichen kann Gleichzeitig habe ich auch einige Nachforschungen angestellt. Nach einiger Zeit sind in PHP nicht viele Timer implementiert, was sehr effizient ist nicht in reinem PHP-Code geschrieben, daher habe ich schließlich darüber nachgedacht, PHP zur Implementierung einer Timer-Kategorie als Lernreferenz zu verwenden.

Implementierung

Bei der Implementierung des Timercodes werden zwei Erweiterungen verwendet, die mit dem PHP-System geliefert werden

Pcntl - Multi -Prozesserweiterung:

Ermöglicht PHP hauptsächlich, viele Unterprozesse gleichzeitig zu öffnen und einige Aufgaben parallel zu verarbeiten.

Spl - SplMinHeap - Kleiner Top-Heap

Bei der Implementierung eines Timers ist die Zeitkomplexität des Einfügens und Löschens sehr gering ist O(logN). Timer wie libevent verwendeten rbtree nach Version 1.4 ebenfalls. Wenn eine verknüpfte Liste oder ein festes Array verwendet wird, muss möglicherweise jedes Einfügen oder Löschen erneut durchlaufen oder sortiert werden .

Prozess

Anleitung

1. Definieren Sie die Timer-Struktur, welche Parameter es gibt usw.
2. Registrieren Sie sie dann alle in unserer Timer-Klasse
3. Rufen Sie die Monitor-Methode der Timer-Klasse auf
4. Der Überwachungsprozess ist eine Endlosschleife, bei der ständig überprüft wird, ob die Spitze des Zeitheaps abgelaufen ist. Ursprünglich hatte ich darüber nachgedacht, jede Sekunde eine Schleife durchzuführen, aber dann dachte ich, dass es ein Problem wäre, jede Sekunde eine Schleife durchzuführen Wenn dies der Fall ist Wenn wir schlafen (1), ist der Timer abgelaufen, sodass wir ihn nicht sofort genau ausführen können und möglicherweise die Gefahr einer Verzögerung besteht. Daher verwenden wir weiterhin usleep (1000), um ihn in Millisekunden anzuzeigen und den Prozess stoppen. Reduzieren Sie die CPU-Last

Beispiel

 /***
 * Class Timer
 */
 class Timer extends SplMinHeap
 {
   /**
   * 比较根节点和新插入节点大小
   * @param mixed $value1
   * @param mixed $value2
   * @return int
   */
   protected function compare($value1, $value2)
   {
     if ($value1['timeout'] > $value2['timeout']) {
       return -1;
     }
     if ($value1[&#39;timeout&#39;] < $value2[&#39;timeout&#39;]) {
       return 1;
     }
     return 0;
   }
   /**
   * 插入节点
   * @param mixed $value
   */
   public function insert($value)
   {
     $value[&#39;timeout&#39;] = time() + $value[&#39;expire&#39;];
     parent::insert($value);
   }
   /**
   * 监听
   * @param bool $debug
   */
   public function monitor($debug = false)
   {
     while (!$this->isEmpty()) {
       $this->exec($debug);
       usleep(1000);
     }
   }
   /**
   * 执行
   * @param $debug
   */
   private function exec($debug)
   {
     $hit = 0;
     $t1  = microtime(true);
     while (!$this->isEmpty()) {
       $node = $this->top();
       if ($node[&#39;timeout&#39;] <= time()) {
         //出堆或入堆
         $node[&#39;repeat&#39;] ? $this->insert($this->extract()) : $this->extract();
         $hit = 1;
         //开启子进程
         if (pcntl_fork() == 0) {
           empty($node[&#39;action&#39;]) ? &#39;&#39; : call_user_func($node[&#39;action&#39;]);
           exit(0);
         }
         //忽略子进程,子进程退出由系统回收
         pcntl_signal(SIGCLD, SIG_IGN);
       } else {
         break;
       }
     }
     $t2 = microtime(true);
     echo ($debug && $hit) ? &#39;时间堆 - 调整耗时: &#39; . round($t2 - $t1, 3) . "秒\r\n" : &#39;&#39;;
   }
 }

Ausführungsergebnisse

Wir haben auch getestet Extremsituationen: Gleichzeitig laufen alle 1000 Timer in 1 Sekunde ab und die Anpassung des Zeitstapels dauert nur 0,126 Sekunden. Dies ist jedoch kein Problem, aber jedes Mal, wenn ein Timer angepasst wird, muss möglicherweise ein untergeordneter Prozess gestartet werden Dies kann zeitaufwändiger sein und es ist möglich, dass diese 1.000 Elemente nicht in einer Sekunde verarbeitet werden können. Dies wirkt sich jedoch auf die Überwachung aus, die beim nächsten Mal weiterhin ausgelöst wird. Wenn der untergeordnete Prozess jedoch beispielsweise nicht gestartet wird, kann dies dennoch der Fall sein durch direkte Ausführung verarbeitet. . . . Natürlich muss es einen besseren Weg geben, aber das ist das Einzige, was mir im Moment einfällt.

Verwandte Empfehlungen:

PHP-Datenbank-Cache-Implementierungsideen


Das obige ist der detaillierte Inhalt vonImplementierungsmethode des PHP-Multitasking-Timers der zweiten Ebene. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn