10.3.4. Dormido

Otra forma con la que puede tener control sobre el comportamiento de su hilos es llamando a sleep() para cesar la ejecución de uno de ellos durante un número de milisegundos dado. En el ejemplo que viene a continuación, si cambia la llamada a yield() por una a sleep(), obtendrá lo siguiente:

//: C11:SleepingTask.cpp
// Calling sleep() to pause for awhile.
//{L} ZThread
#include <iostream>
#include "zthread/Thread.h"
#include "zthread/ThreadedExecutor.h"
using namespace ZThread;
using namespace std;

class SleepingTask : public Runnable {
  int countDown;
  int id;
public:
  SleepingTask(int ident = 0) : countDown(5), id(ident) {}
  ~SleepingTask() {
    cout << id << " completed" << endl;
  }
  friend ostream&
  operator<<(ostream& os, const SleepingTask& st) {
    return os << "#" << st.id << ": " << st.countDown;
  }
  void run() {
    while(true) {
      try {
        cout << *this << endl;
        if(--countDown == 0) return;
        Thread::sleep(100);
      } catch(Interrupted_Exception& e) {
        cerr << e.what() << endl;
      }
    }
  }
};

int main() {
  try {
    ThreadedExecutor executor;
    for(int i = 0; i < 5; i++)
      executor.execute(new SleepingTask(i));
  } catch(Synchronization_Exception& e) {
    cerr << e.what() << endl;
  }
} ///:~

Listado 10.12. C11/SleepingTask.cpp


Thread::sleep() puede lanzar una Interrupted_Exception(sobre las interrupciones aprenderá más adelante), y puede ver que esta excepción se captura en run(). Sin embargo, la tarea se crea y se ejecuta dentro de un bloque try en main() que captura Interrupted_Exception (la clase base para todas las excepciones de ZThread), por lo que ¿no sería posible ignorar la excepción en run() y asumir que se propagará al manejador en main()?. Esto no funcionará porque las excepciones no se propagarán a lo largo de los hilos para volver hacia main(). De esta forma, debe manejar cualquier excepción que pueda ocurrir dentro de una tarea de forma local.

Notará que los hilos tienden a ejecutarse en cualquier orden, lo que quiere decir que sleep() tampoco es una forma de controlar el orden de la ejecución de los hilos. Simplemente para la ejecución del hilo durante un rato. La única garantía que tiene es que el hilo se dormirá durante, al menos, 100 milisegundos (en este ejemplo), pero puede que tarde más después de que el hilo reinicie la ejecución ya que el planificador de hilos tiene que volver a él tras haber expirado el intervalo.

Si debe tener control sobre el orden de la ejecución de hilos, su mejor baza es el uso de controles de sincronización (descritos más adelante) o, en algunos casos, no usar hilos en todo, FIXMEbut instead to write your own cooperative routines that hand control to each other in a specified order.