#!/usr/bin/perl -w
use strict;
use threads;
use Thread::Semaphore;
my $j=0;
my $thread;
my $max_threads=5; #就是写1000,也不会出错,当然系统可能受不了
my $semaphore = Thread::Semaphore ->new($max_threads); #设定允许的最大信号量(线程数)
print localtime(time),"\n";
while()
{
if($j>10){last;}
$j=$j+1;
#获得一个信号量;当执行的线程数为5时,获取失败,主线程等待。直到有一个线程结束,新的信号量可用。回复正常运行;
$semaphore->down();
my $thread=threads->new(\&ss,$j,$j); #创建线程;
#my $thread=threads->new(ss($j,$j)); #这样是不行的
#my $thread=threads->new(ss, $j, $j); #这样是不行的
$thread->detach(); #剥离线程;剥离了,threads->list()里面就没有元素了。主要作用就是不用再来单独join收割线程
print "MMM==$j\t", localtime(time),"\n";
}
#必须存在的部分,用在控制在主线程结束前保证所有剥离的线程已经执行完成。否则的话,当主线程结束时还有从线程没有执行完成,这时从线程将不得不被强行kill掉(皮之不存毛将焉附)。
&waitquit();
print localtime(time),"\n";
sub ss()
{
my ($t,$s)=@_;
sleep(0.001);
#sleep($t);
print "TTT==$s\tLLL==",scalar(threads->list(threads::all)),"\tkkk==$t\t";
#当线程执行完成时,释放信号量。
#但请注意:这个绝不是收割线程
$semaphore->up();
}
sub waitquit_backup
{
print "Waiting to quit...\t",localtime(time),"\n";
#一次性将剩下的线程数都获取出来
my $remaining_thread = scalar(threads->list());
my $num=0;
while($num<$remaining_thread)
{
$semaphore->down();
$num++;
print "$num thread quit...\n";
}
print "All $remaining_thread thread quit\n";
}
#这里似乎有bug,比如读取文件,文件只有3行, 你设置了5个线程,每个线程处理一行
#当然一般情况下一个文件不可能行数少于线程数
#但实际上又没有问题,看来是我没有理解透
#关键在于理解 $semaphore->down() 的含义
# $semaphore->down()旨在取出一个信号,$semaphore->up()是释放一个信号;
# 它们都跟子线程数量没有关系,注意,是没有关系
# 为了控制子线程数量,是人为将线程数与 信号数$semaphore关联起来的
#之所以是$max_threads,那是因为能同时运行的线程数量,最大也就是$max_threads
#如果线程数比$max_threads少,也没关系。
#因为线程结束后,释放了信号,$semaphore->down()
#所以信号数肯定会是,所有子线程都释放后,信号数量==$max_threads
#因为是:my $semaphore = Thread::Semaphore ->new($max_threads); 决定的
#比如$max_threads=5,那么总信号数就是5
#差一个信号未能获取到,就说明有一个子线程还在运行
#另外还要理解$thread->detach();
#这个表示将子线程与主线程剥离
#子线程运行结束后,不用通过$thread -> join()来收割(终结子线程,释放内存空间等),而是自动结束
sub waitquit
{
print "Waiting to quit...\n";
my $num=0;
while($num<$max_threads)
{
$semaphore->down();
$num++;
print "$num thread quit...\n";
}
print "All $max_threads thread quit\n";
}
=pod
重要方法:
threads->create(),创建一个新线程;
threads->join(),收割已经创建的线程;
threads->list(threads::all),返回所有已经创建的线程;
threads->is_joinable(),返回目标线程是否已经完成,等待join;
参考链接:
https://blog.csdn.net/xiaocao9903/article/details/18799373
=cut
perl 多线程
于 2023-12-19 00:28:28 首次发布