Rubyにはプログラムの実行を一定時間止められるsleepメソッドを利用できます。昔は遅いデバイスの応答を待つ時間、処理を止めるために使われることがありました。今でもそういった用途で使うことが可能ですが、それだけではありません。sleepはRubyの並列処理でも利用可能なメソッドです。
今回はRubyのsleepメソッドの使い方と並列処理でのsleepメソッドの使い方を解説します。
Rubyのsleep処理
Rubyでは指定した時間の間だけプログラムの実行を止めるsleepメソッドを利用できます。sleepメソッドの使い方を説明する前に、なぜプログラム言語にこのような処理を止める機能があるのかについて解説します。
低速なデバイス対策
Rubyに限らず多くのプログラム言語には指定した時間だけ処理を待つ機能が用意されています。さらにこのような一定時間処理を待つ機能は、インターネットが普及するかなり前からいろいろなプログラムで使われていました。
昔この機能が必要だった理由の1つは、プログラムを実行するマイコンに対して制御されているデバイスの反応が遅すぎるための対策です。
例えば応答の遅いデバイスにマイコンがリクエストを送信してもすぐに応答を返せません。そのためマイコンがリクエストを送信したら、数秒間待ってデバイスからの応答を受ける処理を実行するのが一般的でした。
そのような処理で使われたのが今回紹介するRubyのsleepのような、プログラムの処理を一定時間止める機能です。
インターネットの遅延対策
高速なCPUやデバイスが手に入る今の時代、処理が終わるまで数秒待たなけれならない処理として挙げられるのがインターネットの遅延です。遠い外国のサーバーにアクセスするのに時間がかかるケースや、サーバーが混んでいて処理を待たされるケースなど、待たされるケースはいろいろ考えられます。
またWebスクレイピングでWebサイトにアクセスする場合、短時間に連続してアクセスすると攻撃とみなされてアクセスを遮断されるケースに対する注意が必要です。このようにインターネットにアクセスするプログラムでは、Rubyのsleepを利用して次の処理まで待機するプログラムが使われます。
sleepだけに頼ってはいけない
これまで紹介したように昔から処理を待つプログラムが使われており、インターネットを介した処理などでは今でも使われています。
ただし安易にsleepで処理を止めるのは必ずしも正しい処理ではありません。リクエストに対する応答があったら直ちに処理を継続できるように、sleepの機能と応答をチェックする機能をうまく組み合わせたプログラムを作らなければなりません。
Rubyのsleepメソッドの使い方
Rubyのsleepメソッドは、指定した数値の秒数だけ処理を止めるシンプルなメソッドです。次からsleepメソッドの文法とその使い方について解説します。
sleepメソッドの文法
sleepメソッドは引数に指定した数の秒数だけ処理を中断します。なお引数として小数点数の付いた数も指定できますが、マイナスの付いた数は指定できません。
sleepメソッドの文法
sleep 秒数
sleepメソッドの例
sleep 10 # 10秒処理を中断する sleep 0.01 # 0.01秒(10マイクロ秒)処理を中断する
秒数を省略した場合
sleepメソッドで秒数を省略した場合、そのプログラムを永久に中断します。この場合、プログラムが終了する訳ではありません。例えば他のスレッドからの再開の指令を受け取ると、sleepを中断して処理を再開できます。
Rubyはマルチスレッドのプログラミングに対応しており、Threadクラスを利用することで並列処理のプログラムを作ることが可能です。そのようなプログラムでは、1つのスレッドをsleepメソッドで停止し、何かのイベントに対応してThread.runメソッドでそのスレッドを再開させる、といったプログラムが作れます。
永久に処理を中断処理の例
it = Thread.new do sleep puts 'I wake up now!' end puts 'Wake up' sleep 3 it.run
この例は、Thread.newで処理を中断しているスレッドを生成し、’Wake up’を表示した3秒後に「it.run」で中断しているスレッドを再開させ、’I wake up now!’を表示させています。
sleepメソッドから見たThreadの基本
先ほどsleepに数字を指定しないでスレッドを中断させた場合、Thread.runメソッドで再開できると説明しましたが、これはsleepメソッドがTheradを停止状態にする効果を利用しています。
とはいえTheradのことが分らないとsleepも使えません。それでsleepとTheradの関係について解説します。
Theradの4つの状態
ThreadとはRubyにおける並列プログラミングの仕組みで、複数の処理を同時に実行することが可能です。さらにTheradを停止状態にしておき、トリガーに応じて稼働させたり、終了させることもできます。
Threadには次の4つの状態があり、状態を変更することでThreadを稼働させたり停止することが可能です。
実行状態:Threadが作られたばかり、またはThred.runで切り替えた後の状態です。
停止状態:Theradはすぐに稼働できるものの動作していいない状態です。Thread.stopでこの状態にできます。
終了処理中:Theradのkillメソッドで終了する直前の状態です。
終了状態:Theradのkillメソッドが完了し、メモリからも無くなった状態です。
sleepは実行状態を停止状態にする
先ほど紹介したTheradの4つの状態の中で、実行状態から停止状態にするのがsleepメソッドです。停止状態はThreadがメモリに残っていてすぐに動かせるものの実行が止まった状態を意味します。
Threadの外から停止状態にするにはThread.stopを使用します。そしてThread内で停止状態にする際にsleepメソッドを使います。
なおThreadの内からsleepメソッドを利用して処理で停止した場合は、内部から処理を再開させる手段が無いので注意してください。
sleepしたらThread.runで実行に戻せる
先ほど紹介したようにsleepを引数無しで実行すると永久に処理を停止しますが、これを実行するとThreadの中から実行状態に戻すことはできません。処理を再開させる場合は、Threadの外からThread.runを実行します。
次にThread.runを利用して停止したThreadを再開させるプログラムの例を紹介します。
永久に処理を中断処理の例
it = Thread.new do sleep puts 'I wake up now!' end puts 'Wake up' sleep 3 it.run
この例では新しいTheradの「it」を作り、すぐにsleepメソッドで処理を停止しています。そして「it.run」でThreadにrunメソッドを適用して、処理を再開しています。
まとめ
これまで紹介したようにsleepメソッドは指定した秒数だけ処理を中断させるメソッドです。昔は遅いデバイスに合わせて数秒待たせるプログラムもありましたが、sleepメソッドを使えばRubyでもそのようなプログラムを作れます。
また引数無しでsleepメソッドを実行すると永久に処理を中断させます。そしてこの機能はRubyによる並列処理で、スレッドを待機させる場合に使います。もしRubyで並列処理を作る場合はsleepメソッドをうまく活用することで、無駄にCPUを使うことなく必要な時だけ動作するプログラムを実現できます。
ぜひsleppの機能を理解しRubuのスキルアップに役立ててください。