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.