(1)直接执行子程序,按顺序由上到下执行代码,一个线程内执行
sub test0{
print “test0 0\n”;
print “test0 1\n”;
print “finish test0\n”;
}
&test0;
print "main 0\n";
print "main 1\n";
结果:test0 0
test0 1
finish test0
main 0
main 1
(2)用create创建线程后的执行过程
use threads;
sub test0{
print "test0 0\n";
print “test0 1\n”;
print “finish test0\n”;
}
my $thr0 = threads->create(\&test0);
print "main 0\n";
print "main 1\n";
$thr0->join;
结果:
main 0
main 1
test0 0
test0 1
finish test0
可见用create创建线程以后,不等test0子程序执行完,就开始执行下面的打印信息,直到调用join函数,才将test0子程序执行过程中的打印信息打印出来,join操作的意思是:“对该线程收尸并收集该线程的返回值”。
use threads;
sub test0{
print "test0 0\n";
print “test0 1\n”;
print “finish test0\n”;
}
my $thr0 = threads->create(\&test0);
sleep 2;
print "main 0\n";
print "main 1\n";
$thr0->join;
结果:
test0 0
test0 1
finish test0
main 0
main 1
sleep 2时子线程thr0执行完。子线程先执行完毕,但是父线程还没对它进行join,这时子线程一直处于joinable的状态,其实这个时候子线程基本已经失去意义了,它的返回值和相关信息都保存在线程栈(或调用栈call stack),当父线程对其进行join()的时候,自然能从线程栈中找到返回值或某些信息的栈地址从而取得相关数据,也能从现在开始对其进行收尸行为。线程的状态有create-running-finished execution后进入joinable-然后可以joined/unjoined/undetached
对比上面的代码,可以理解为加入create子线程后,在主线程中执行时,用create创建的子线程和主线程并行执行。
线程运行在进程内部,每个进程都至少有一个线程,即main线程,它在进程创建之后就存在。一个进程中除了主main进程外还可以create很多个线程,所有线程全都在进程内部并行地被调度、运行,就像多进程一样。每个线程都共享了主进程的很多数据,除了线程自己所需要的数据,它们都直接使用父进程的变量、子程序。
(3)create多线程
按顺序create多线程时,create第二个线程时第一个线程就执行完了
use threads;
&test_thread;
&test0;
&test1;
sub test0{
print "test0 0\n";
print “test0 1\n”;
print “finish test0\n”;
}
sub test1{
print "test1 0\n";
print “test1 1\n”;
print “finish test1\n”;
}
sub test_thread{
my $thr0 = threads->create(\&test0);
print "after create thread0\n";
my $thr1 = threads->create(\&test1);
print "after create thread1 and thread0\n";
foreach(threads->list(threads:all)){
if($_->is_joinable()){
$_->join();
}
}
print "finish test_thread\n";
}
结果:
after create thread0
test0 0
test0 1
finish test0
after create thread1 and thread0
test1 0
test1 1
finish test1
finish test_thread
test0 0
test0 1
finish test0
test1 0
test1 1
finish test1
4)线程id
sub test_thread{
my $thr0 = threads->create(\&test0);
print "after create thread0\n";
my $thr1 = threads->create(\&test1);
print "after create thread1 and thread0\n";
my $cur_id = threads->tid();
my $thr0_id = $thr0->tid();
my $thr1_id = $thr1->tid();
print "\$cur_id:$cur_id \$thr0_id:$thr0_id \$thr1_id:$thr1_id\n";
foreach(threads->list(threads:all)){
if($_->is_joinable()){
$_->join();
}
}
print "finish test_thread\n";
}
新加入的打印id的代码:
$cur_id:0 $thr0_id:1 $thr1_id:2
三个线程主线程、thr0、thr1的id不同,通过id可以区分不同的线程。可以理解为在主线程主干上分出来了两个分支作为分支线程 。
threads->self()可以获取当前线程对象。类方法threads->tid()来获取当前线程对象的ID。对于已知道tid的线程,可以使用类方法threads->object($tid)
去获取这个tid的线程对象。注意,object()只能获取正激活的线程对象,对于joined和detached线程,都返回undef,不仅如此,对于无法收集的线程对象,object()都返回undef,例如收集$tid不存在的线程。
5)线程状态
所以,threads->list()只能统计未detach、未join的线程,running返回的是正在运行子程序主体的线程,joinable返回的是已完成子程序主体的线程,all返回的是它们之和。
$thr->is_running()如果该线程正在运行,则返回true
$thr->is_joinable()如果该线程已经完成了子程序的主体(即running刚结束),且未detach未join,换句话说,这个线程是joinable,于是返回true
$thr->is_detached() threads->is_detached() 测试该线程或线程自身是否已经detach