スクラッチは、マルチスレッドに対応したビジュアルプログラミング言語です。
こちらでは、マルチスレッドで、どのような優先順位で処理されていくのかを詳しく解説します。
スレッドとは?
スレッドとは、スクラッチのプログラムを実行する際の最小単位のプログラムのことです。
「スクラッチでプログラミング001|スクラッチの画面について」で、プログラムのかたまりのことを「スクリプト」と説明しましたが、スクラッチでは、多くの場合1スクリプトが1スレッドに対応しています。
マルチスレッドとは?
マルチスレッドとは、複数のスレッドを並行して進めることで、スクラッチは、マルチスレッドに対応したビジュアルプログラミング言語です。
スクラッチでは、スプライトごとにプログラムを作って、同時に動いているように見えますが、実際は、プログラムは同時に実行していません。
スクラッチでは、プログラムを実行する優先順位があります。
スクラッチのプログラムの優先順位
- レイヤーが一番上のスプライトが最初に実行される
- スプライトの重なり順にスプライトが実行される
- すべてのスプライトが実行されたら、最後にステージが実行される
- 同じスプライトの中では、作ったハットブロックの順で実行される
こちらが、スクラッチで、プログラムを実行する優先順位です。
レイヤーが一番上のスプライトが最初に実行される
スクラッチでは、レイヤーが一番上のスプライトが最初に実行されます。
レイヤーとは、透明の画用紙のようなもので、スクラッチでは、レイヤーのことを「層」と表現します。
具体的にレイヤーとはどのようなものなのか確認してみましょう。
スクラッチの新しいファイルを開いて、「スプライトを選ぶ」からスプライトを追加します。
今回は、リンゴ(Apple)を追加しました。
すると、リンゴがスクラッチキャット(スプライト1)の上に重なっているのが分かります。
つまり、1層目のレイヤーにリンゴ、2層目のレイヤーにスクラッチキャットがいるということです。
この場合、一番上のリンゴが一番最初に実行されます。
さらに、もう一つバナナ(Bananas)のスプライトを追加しました。
今度は、バナナが一番前で、リンゴ、スクラッチキャットの順で重なっているのが分かります。
この場合、一番上のバナナが一番最初に実行されます。
スプライトの重なり順にスプライトが実行される
スプライトが複数ある場合は、スプライトの重なり順にスプライトが実行されます。
実際に、スクラッチで処理の順番を確認してみましょう。
まず、変数「x」を作って、中身を空にしておきます。
(画像をクリックすると大きくなります。)
次に、それぞれのスプライトのプログラムを、このようにプログラミングします。
こちらでは、緑の旗が押されたときに、変数「x」にスプライトの名前を付けたす処理をしています。
1層目のレイヤーに「バナナ」、2層目のレイヤーに「リンゴ」、3層目のレイヤーに「スクラッチキャット」の順番で、緑の旗をクリックすると、このような結果になりました。
変数「x」の中身を確認すると「|Bananas|Apple|スクラッチキャット」となっていますよね。
つまり、レイヤの順番と同じ、「バナナ」「リンゴ」「スクラッチキャット」の順に処理されたということです。
今度は、1層目のレイヤーに「リンゴ」、2層目のレイヤーに「スクラッチキャット」、3層目のレイヤーに「バナナ」の順番に並び替えます。
この状態で、緑の旗をクリックすると、変数「x」は「|Apple|スクラッチキャット|Bananas」となりました。
こちらも、レイヤの順番と同じ、「リンゴ」「スクラッチキャット」「バナナ」の順に処理されているのが分かります。
すべてのスプライトが実行されたら、最後にステージが実行される
スクラッチでは、ステージのスクリプトエリアにもプログラムを作ることができます。
ステージのプログラムが実行されるのは、すべてのスプライトが実行された最後です。
ステージにも、スプライトと同じように変数「x」を設定して確認してみます。
この状態で、緑の旗をクリックすると、変数「x」は「|Apple|Bananas|スクラッチキャット|背景」となりました。
スプライトのレイヤの順番は、「リンゴ」「バナナ」「スクラッチキャット」になっているので、プログラムもその順番で処理されています。
そして、最後に「ステージ」のプログラムが実行されているのが分かります。
ステージにメインのプログラムを作ると、最後に実行されるので、注意してプログラミングしましょう。
同じスプライトの中では、作ったハットブロックの順で実行される
スプライトのスクリプトエリアには、複数のスレッドを作ることができ、同じスプライトの中では、作ったハットブロックの順で実行されます。
ハットブロックとは、上の部分が丸くなっているのが特徴で、そのスクリプトを開始するためのブロックのことです。
ブロックパレットからスクリプトエリアに追加されたハットブロックから、順にプログラムが実行されます。
実際に、スクラッチで処理の順番を確認してみましょう。
まず、2つのハットブロックを用意します。
上の「緑の旗が押されたとき」ブロックが最初に作ったハットブロックです。
作ったハットブロックの順で実行されるということは、最初に①が実行されて、変数が「0」になり、次に②が実行されて変数が「1」になるはずです。
まず、緑の旗を押すと変数が「1」になりました。
これは、予想通りです。
今度は、変数のブロックを入れ替えると、変数は「0」になります。
そして、新しく「緑の旗が押されたとき」ブロックを追加(③)して、実行すると、③が最後に実行されて、変数は「3」になります。
①②の「緑の旗が押されたとき」ブロックを削除して、新しく「緑の旗が押されたとき」ブロックを追加(④)すると、一番に実行されるのは③です。
そして次に④が実行されて、変数は「1」なります。
このように、ハットブロックが作られた順に実行されます。
スレッドの切り替わるタイミング
ブロックには、こちらのように処理を繰り返すブロックがあります。
スクラッチでは、繰り返し処理の中のプログラムが全て実行されて、繰り返しの最初に戻るタイミングにスレッドが切り替わります。
実際にプログラムを作って確認してみます。
こちらは、リスト「処理順」を作って、変数「x」がどのように変化するのか記録するプログラムです。
「緑の旗が押されたとき」ブロックは①が最初に作ったブロックなので、プログラムの優先順位からいえば、①のプログラムが終わってから②のプログラムが処理されるので、リスト「処理順」は以下のように記録されるはずですが、結果はどうでしょうか。
- 0(①のプログラム)
- 0(①のプログラム)
- 0(①のプログラム)
- 1(②のプログラム)
- 1(②のプログラム)
- 1(②のプログラム)
こちらが実際に実行した結果です。
「0」「1」が交互に記録されていますよね。
つまり、①②のスレッドが交互に実行されたということです。
そのスレッドが切り替わるタイミングが、繰り返し処理の中のプログラムが全て実行されて、繰り返しの最初に戻るタイミングです。
もう少し実験をしてみます。
今度は、①に変数「x」を「2」にするプログラムを追加しました。
こちらの実行すると、以下のように記録されています。
- 0(①のプログラム)
- 2(①のプログラム)
- 1(②のプログラム)
- 0(①のプログラム)
- 2(①のプログラム)
- 1(②のプログラム)
- 0(①のプログラム)
- 2(①のプログラム)
- 1(②のプログラム)
スレッドが切り替わるタイミングが、繰り返し処理の中のプログラムが全て実行されて、繰り返しの最初に戻るタイミングです。
変数「x」を「2」にするプログラムは、繰り返し処理の中のプログラムです。
繰り返し処理の中のプログラムが終わって、繰り返し処理の最初に戻るタイミングでスレッドが切り替わっているのが分かります。
待ち時間処理でもスレッドが切り替わる
実は、もう一つスレッドが切り替わるタイミングがあります。
それは、こちらのように待ち時間があるブロックを使用した場合です。
待ち時間を設定できる代表的なブロックと言えば、「〇秒待つ」ブロックですよね。
こちらを①のプログラムに入れて処理の順番を確認してみましょう。
変数「x」を「0」にするプログラムの下に、「〇秒待つ」ブロックで1秒待つ処理を入れています。
こちらを実行すると、以下のように記録されています。
- 0(①のプログラム)
- 1(②のプログラム)
- 1(②のプログラム)
- 1(②のプログラム)
- 2(①のプログラム)
- 0(①のプログラム)
- 2(①のプログラム)
- 0(①のプログラム)
- 2(①のプログラム)
「〇秒待つ」ブロックの処理のタイミングで、スレッドが切り替わり、②のプログラムが3回まとめて処理されているのが分かります。
つまり、1秒停止している間に②のプログラムが実行されたということです。
待ち時間処理でもスレッドが切り替わることが分かりましたが、待ち時間の設定で処理する順番が変わることがあります。
例えば、「〇秒待つ」ブロックで0秒に設定して実行してみましょう。
こちらを実行すると、以下のように記録されています。
- 0(①のプログラム)
- 1(②のプログラム)
- 2(①のプログラム)
- 0(①のプログラム)
- 1(②のプログラム)
- 2(①のプログラム)
- 0(①のプログラム)
- 1(②のプログラム)
- 2(①のプログラム)
秒数を変えるだけで、処理順が変わりましたよね。
これは、②の繰り返し処理がすべて終わるよりも、待つ時間が短いためです。
PC環境にもよりますが、待つ時間の「0.03秒」と「0.04秒」が処理の別れ目でした。
よく、一瞬だけ処理を止めたいときに「0秒」を設定する人がいますが、「0秒」に設定したとき、プログラムの処理の順番がどうなるのか意識するようにしましょう。
必ず順番通りに処理させたいときの対処法
複数のスプライト間で変数を使用していると、優先順位から思い通りに動作しないことがあります。
それは、赤い丸(●)を押してプログラムを中断したときなどでよく起こります。
必ず順番通りに処理させたいときは、「▢へ移動する」ブロックや「〇層▢(レイヤー)」ブロックを使って、レイヤーの順番を指定しておきましょう。
最初にレイヤーの順番を指定しておけば、途中でプログラムを中断したときも、その順番で処理されていきます。(プログラム内容によってはされない場合もあり)