tid. magic 1 0 Worker 1 first job in while loop 1 1 Worker 1 first job in do_work 2 0 Worker 2 first job in while loop 2 1 Worker 2 first job in do_work 1 0 Worker 1 second job in while loop 1 1 Worker 1 second job in do_work 2 0 Worker 2 second job in while loop 2 1 Worker 2 second job in do_work 1 -1 Worker 1 after exiting while loop 2 -1 Worker 2 after exiting while loop #### tid. magic 1 0 Worker 1 first job in while loop 1 1 Worker 1 first job in do_work 1 0 Worker 1 second job in while loop 1 1 Worker 1 second job in do_work 1 -1 Worker 1 after exiting while loop 2 0 Worker 2 first job in while loop 2 1 Worker 2 first job in do_work 2 0 Worker 2 second job in while loop 2 1 Worker 2 second job in do_work 2 -1 Worker 2 after exiting while loop #### tid. magic 2 0 Worker 2 first job in while loop 2 1 Worker 2 first job in do_work 2 0 Worker 2 second job in while loop 2 1 Worker 2 second job in do_work 2 -1 Worker 2 after exiting while loop 1 0 Worker 1 first job in while loop 1 1 Worker 1 first job in do_work 1 0 Worker 1 second job in while loop 1 1 Worker 1 second job in do_work 1 -1 Worker 1 after exiting while loop #### my $semSTDOUT : shared; sub tprint{ lock $semSTDOUT; print @_; } tprint "$tid: Some text"; #### sub run_external_command { my ( $job, $tid ) = @_; $q_PRINT->enqueue( "Thread $tid is running exteral job $job" ); local( *w_IN, *w_OUT, *w_ERR ); my $pid = open3( \*w_IN, \*w_OUT, \*w_ERR, '/bin/sleep', int( rand($DEFAULTS->{'random'} ) ) ); waitpid( $pid, 0 ); return $DEFAULTS->{'ret_success'}; } #### #! perl -slw use strict; use threads; use threads::shared; use Thread::Queue; use constant { RANDOM => 4, THREADS => 4, JOBS => 20, }; my $semSTD :shared; sub tprint { my $tid = threads->tid; lock $semSTD; print "[$tid] ", @_; } my $die_early :shared = 0; $SIG{ INT } = sub { tprint "Early termination requested"; $die_early = 1; }; sub worker { tprint "worker started"; my( $Q ) = @_; while( !$die_early and defined( my $job = $Q->dequeue ) ) { tprint "processing job:$job"; my $pid = open my $PIPE, '-|', "sleep " . int( rand RANDOM ) or die $!; tprint "waiting for pid: $pid"; waitpid $pid, 0; tprint "pid: $pid done"; } tprint "Worker ending"; return 1; } my $Q = new Thread::Queue; $Q->enqueue( map "JOB-$_", 1 .. JOBS ); $Q->enqueue( (undef) x THREADS ); tprint "Queue populated"; my @threads = map threads->new( \&worker, $Q ), 1 .. THREADS; tprint "Workers started; waiting..."; $_->join for @threads; print "Program complete"; __END__ C:\test>881217 [0] Queue populated [1] worker started [1] processing job:JOB-1 [1] waiting for pid: 1740 [2] worker started [2] processing job:JOB-2 [1] waiting for pid: 1056 [2] pid: 2684 done [2] processing job:JOB-4 [1] waiting for pid: 2116 [3] worker started [3] processing job:JOB-6 [3] waiting for pid: 3244 [0] Workers started; waiting... [4] worker started [4] processing job:JOB-7 ... [3] pid: 1112 done [3] processing job:JOB-20 [3] waiting for pid: 4048 [2] pid: 1728 done [1] pid: 3432 done [2] Worker ending [1] Worker ending [4] pid: 3924 done [4] Worker ending [3] pid: 4048 done [3] Worker ending Program complete