やまたのおろちって本体一つに八つの首があるんだって。3だとキングギドラで、4がヒュドラで、16だとミズノエリュウ、だったと思うの。で、このたくさんの首の一つ一つがドラゴンの顔になってて、口があって……。まぁ、ようするに、そんな彼らに酒を飲んでもらおうというコンセプトで、スレッドプログラミングの話をしてみようと思うんだ。
まずはシングルスレッドのお話。
まずはシンプルに、ふつーのシングルスレッド。代表の一本の首だけが飲ンベって想定で。 流れとしては一本の首がごきゅごきゅと酒ツボを飲み干すっと。
Imports System.Threading
Module OrochSTA
Public Sub Main()
Dim hontai As New Thread( _
New ThreadStart(AddressOf DrinkSAKE)) '
hontai.Start()
hontai.Join()
Console.WriteLine("ぷはーっ!")
Stop
End Sub
' 酒のみスレッド
Private Sub DrinkSAKE()
'酒ツボの中の酒の量
Dim totalSAKE As Integer = 1000
Dim totalDrunk As Integer = 0
Dim nowDrink As Integer
Dim oneDrink As New Random
Dim oneBreath As New Random
'酒ツボの中の酒を飲み干す
While (totalDrunk <= totalSAKE)
'一回飲むたびに息継ぎ
Thread.Sleep(oneBreath.Next(30, 60))
'一回ぐび
nowDrink = oneDrink.Next(1, 100)
Console.WriteLine("{0} リットル ぐびっ", nowDrink)
'全部でどれくらい飲んだ?
totalDrunk += nowDrink
End While
End Sub
End Module
この場合、
酒飲みはまだ一個の首でやってる。酒ツボも一つだけだから、さくーっとのんで終わり。で、つぎに、
このおろちの首をクラス化して、その一本の首に酒を飲ませてみる。これが大事な前フリw。あとで首がたくさんになるからね。
Imports System.Threading
Module OrochSTA
Public Sub Main()
Dim myHead As New OrochiHead
myHead.Drink()
Stop
End Sub
'おろちの首をクラス化
Private Class OrochiHead
'酒を飲むメソッド
Public Sub Drink()
Dim sakeZuki As New Thread( _
New ThreadStart(AddressOf DrinkSAKE)) '
sakeZuki.Start()
sakeZuki.Join()
Console.WriteLine("ぷはーっ!")
End Sub
' 酒のみスレッド
Private Sub DrinkSAKE()
'酒ツボの中の酒の量
Dim totalSAKE As Integer = 1000
Dim totalDrunk As Integer = 0
Dim nowDrink As Integer
Dim oneDrink As New Random
Dim oneBreath As New Random
'酒ツボの中の酒を飲み干す
While (totalDrunk <= totalSAKE)
'一回飲むたびに息継ぎ
Thread.Sleep(oneBreath.Next(30, 60))
'一回ぐび
nowDrink = oneDrink.Next(1, 100)
Console.WriteLine("{0} リットル ぐびっ", nowDrink)
'全部でどれくらい飲んだ?
totalDrunk += nowDrink
End While
End Sub
End Class
End Module
で、首をクラス化することで、首が酒を飲む、というメソッドがラッピング。こうすると首一本のやるべきことが明確になる。そこで、飲ンベ首をデリゲートに登録して、さらに別スレッドで飲ませるように書き換えてみる。
Imports System
Imports System.Threading
Module OrochSTA
Delegate Sub DrinkingSAKE()
Public Sub Main()
'本体で首が別々に酒飲みするのを身構える
Dim ts As New ThreadStart(AddressOf OrochiDrinking)
Dim workerThread As New Thread(ts)
workerThread.SetApartmentState(ApartmentState.STA)
workerThread.Start()
workerThread.Join()
Stop
End Sub
Private Sub OrochiDrinking()
'まずは首を八本で飲んでみる
Dim headCount As Integer = 8
'全部の首が酒を飲み干す
For i As Integer = 1 To headCount
HeadDrinking(i)
Next
End Sub
Private Sub HeadDrinking(ByVal headNo As Integer)
'指定した番号の首に酒を飲ませる
Dim myHead As New OrochiHead(headNo)
Dim gubi As New DrinkingSAKE(AddressOf myHead.Drink)
'酒飲み開始とともに、酔っ払い待ち行列へ戻す
gubi.Invoke()
End Sub
'おろちの首をクラス化
Private Class OrochiHead
Private meNumber As Integer
'何番目の首なのかを保存
Public Sub New(ByVal headNo As Integer)
meNumber = headNo
End Sub
'酒を飲むメソッド
Public Sub Drink()
Dim sakeZuki As New Thread( _
New ThreadStart(AddressOf DrinkSAKE)) '
sakeZuki.Start()
sakeZuki.Join()
Console.WriteLine("ぷはーっ! {0}番目の首、飲み終わり!", meNumber)
End Sub
' 酒のみスレッド
Private Sub DrinkSAKE()
'酒ツボの中の酒の量
Dim totalSAKE As Integer = 1000
Dim totalDrunk As Integer = 0
Dim nowDrink As Integer
Dim oneDrink As New Random
Dim oneBreath As New Random
'酒ツボの中の酒を飲み干す
While (totalDrunk <= totalSAKE)
'一回飲むたびに息継ぎ
Thread.Sleep(oneBreath.Next(30, 60))
'一回ぐび
nowDrink = oneDrink.Next(1, 100)
Console.WriteLine("{0}番目の首が {1} リットル ぐびっ", meNumber, nowDrink)
'全部でどれくらい飲んだ?
totalDrunk += nowDrink
End While
End Sub
End Class
End Module
さて、こんなカンジで、首の一本一本が順番に酒を飲んで、順番に飲み終わり、をシングルスレッドで動いてるってことに置き換えてもこれだけの方法があったりする。でもね、飲ンベ首が増えたら、待たせるとウルサイから皆せーの!で飲んじゃいなYO!ってことで並列化させようと思うんだ。これがマルチスレッドでの動き。それはまた次にね