達成したいことに応じて、Perlでスレッドを強制終了する方法は実際にはいくつかあります。
次のコードを例として取り上げましょう。
use strict;
use warnings;
use threads;
use Thread::Queue;
# Create the shared queue (used by the threads):
my $queue = Thread::Queue->new();
sub main {
# Initialise the shared queue:
$queue->enqueue("A", "B", "C", "D", "E", "F");
print "Total number of items: " . $queue->pending() . "\n";
$queue->end(); # signal that there is no more work to be sent...
# Create 3 threads:
threads->create('do') for ( 0..2 );
print "Number of current threads: " . threads->list() . "\n";
foreach my $thread ( threads->list() ) { # for each thread...
$thread->join(); # wait the thread to finish all its work...
print "Number of items in the queue: " . $queue->pending() . "\n" if defined $queue->pending();
print "Number of current threads: " . threads->list() . "\n";
}
}
sub do {
# Retrieve the current thread ID:
my $threadID = threads->self()->tid();
# Setup the thread's kill signal handler:
local $SIG{KILL} = sub { threads->exit() };
while ( defined (my $item = $queue->dequeue()) ) { # for each element in the queue...
print "(Thread-" . $threadID . "): Do something with item '$item'...\n";
sleep 1 + $threadID;
print "(Thread-" . $threadID . "): Finished to use item '$item'...\n";
}
}
main();
上記のコードは3つのスレッドを生成します。各スレッドは、キューが空になるまで共有キューの要素を取得して処理します。
この場合、これ以上要素がキューに追加されないことを宣言したため(つまり、$ queue-> end())、スレッドは、キューのすべての要素を処理した後、(メインに)参加します。実際、$ thread-> join()を使用して、 $threadが参加するのを待つようにメインに言っています。
$ queue-> end()の宣言を省略した場合、スレッドはメインに参加しませんが、キューの新しい要素に対して保留状態のままになります。
ここで、スレッドを強制終了する場合は、2つのオプションがあります。スレッドを強制終了するが、最初に実行していることを終了させるか、単に(残酷に)スレッドをすぐに強制終了します。Perlでは、両方ともスレッドシグナリングを介して実現されます。
最初のケース(つまり、スレッドに作業を終了し、その後、共有キューの処理を停止するように指示する場合)は、$ thread-> kill('KILL')-> join()を使用する必要があります。
foreach my $thread ( threads->list() ) { # for each thread...
$thread->kill('KILL')->join(); # wait the thread finish its work and kill it...
print "Number of items in the queue: " . $queue->pending() . "\n" if defined $queue->pending();
print "Number of current threads: " . threads->list() . "\n";
}
一方、後者の場合(つまり、スレッドをすぐに強制終了する場合)は、 $ thread-> kill('KILL')-> kill()を使用する必要があります。
foreach my $thread ( threads->list() ) { # for each thread...
$thread->kill('KILL')->kill(); # kill the thread immediately...
print "Number of items in the queue: " . $queue->pending() . "\n" if defined $queue->pending();
print "Number of current threads: " . threads->list() . "\n";
}
もちろん、スレッド自体を強制終了する場合は、 threads-> exit()を呼び出すか、単にreturn:を使用する必要があります。
sub do {
...
threads->exit(); # kill the thread...
...
}