我的脚本应该有n个子程序( my_proc )同时运行,每个子程序运行bash脚本,一个子程序( check_procs )检查子程序是否已完成。
use strict;
use threads;
use threads::shared;
my %proc_status :shared;
my %thr;
foreach my $i (1,2,3,4) {
$proc_status{$i}=0;
}
sub my_proc {
my $arg=shift(@_);
while (1) {
sleep(2);
print "Proc $arg Started\n";
#exec("/bin/bash","sleep_for_10_sec.bash") or die("Can't exec"); # case 1
#`sleep_for_10_sec.bash &`; # case 2
print "Proc $arg Finished\n";
{
lock(%proc_status);
$proc_status{$arg}=1;
}
}
}
sub check_procs {
my $all_finished;
while (! $all_finished) {
sleep 5;
print "CHECK: \n";
$all_finished=1;
foreach my $num (1,2,3,4) {
if ($proc_status{$num} == 1) {
print "CHECK: procedure $num has finished\n";
} else {
$all_finished=0;
}
}
}
print "All jobs finished\n";
}
foreach my $num (1,2,3,4) {
$thr{"$num"} = new threads \&my_proc,$num;
}
my $thr_check= new threads \&check_procs;
$thr_check->join();
这是sleep_for_10_sec.bash
ls
# bunch of other stuff
sleep 10
echo "finished sleep"
我不希望 my_proc sub等待“sleep_for_10_sec.bash”命令执行,浏览后我发现 #case1 或# case2 应该有效,但它们都失败了。
#case1的输出:
Proc 1 Started
[ls result]
finsihed sleep
#case2的输出:
Proc 1 Started
Proc 2 Started
Proc 3 Started
Proc 4 Started
CHECK:
CHECK:
Proc 4 Finished
Proc 2 Finished
Proc 3 Finished
Proc 1 Finished
Proc 3 Started
Proc 1 Started
Proc 2 Started
Proc 4 Started
CHECK:
CHECK: procedure 1 has finished
CHECK: procedure 2 has finished
CHECK: procedure 3 has finished
CHECK: procedure 4 has finished
但我期待这样的事情:
Proc 1 Started
Proc 2 Started
Proc 3 Started
Proc 4 Started
Proc 1 Finished
Proc 1 Started
Proc 3 Finished
Proc 3 Started
Proc 4 Finished
Proc 4 Started
Proc 2 Finished
Proc 2 Started
CHECK:
CHECK:
CHECK:
CHECK: procedure 1 has finished
CHECK: procedure 2 has finished
CHECK: procedure 3 has finished
CHECK: procedure 4 has finished
实际上,如果将输出重定向到“> log”,我会得到想要的结果,但无论如何:
Proc 1 Started
Proc 2 Started
Proc 3 Started
Proc 4 Started
等待“sleep_for_10_sec.bash”完成。
这是我第一个使用“thread”和“exec”的项目,有人可以帮我吗?
答案 0 :(得分:1)
exec
不应与线程结合使用。 exec
在当前进程中启动一个新程序,因此当您从一个线程调用exec
时,线程正在执行的程序将消失。由于线程没有要执行的程序,exec
也会杀死线程。
我不清楚为什么案例2不起作用(编辑:见下面的ikegami评论)。我认为它会启动进程,在后台运行它,并允许Perl线程立即继续。它似乎没有这样做,但这段代码将:
system("/bin/bash sleep_for_10_sec.bash &"); # case 3
答案 1 :(得分:1)
Object get() { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Object> response = executor.submit(() -> { return execute(); }); executor.shutdown(); executor.awaitTermination(10, TimeUnit.SECONDS); if (executor.isTerminated()) { return response.get(); } executor.shutdownNow(); return get(); }
exec("/bin/bash","sleep_for_10_sec.bash") or die("Can't exec"); # case 1
用另一个程序替换当前进程中运行的程序。同时,现有的线程被终止(因为他们想要执行的程序不再存在),取而代之的是执行新程序的单个线程。
这意味着exec
永远不会返回(错误除外)。线程或没有线程,exec
不是您想要的,因为您不希望您的程序停止运行。
但我希望这样的事情:
您是否确定要每两秒启动一次exec
4次(意味着您最多可以同时运行20个),因为您想要的输出显示?
您确定不关心sleep_for_10_sec.bash
是否完成,因为您想要的输出显示?
如果是这样,你为什么要使用线程呢?您可以简单地使用以下内容:
sleep_for_10_sec.bash
我想你想要
sub start {
my $num = shift;
say "Proc $num Started";
system('bash -c sleep_for_10_sec.bash &');
say "Proc $num Finished";
}
for my $pass (1..2) {
start($_) for 1..4;
sleep 2;
start($_) for 1..4;
sleep 2;
start($_) for 1..4;
sleep 1;
if ($pass == 1) {
say "CHECK:";
} else {
say "CHECK: procedure $_ has finished" for 1..4;
}
}