What modules should I look at for doing multithreading in Perl?
I\'m looking to do something fairly low performance; I want threads is to run multiple workers simultaneo
If performance isn't a big issue, then fork
ing multiple processes will probably be a lot easier than dealing with threads. I frequently use Parallel::ForkManager which is very simple, but very good at what it does.
Coro is a nice module for cooperative multitasking.
99% of the time, this is what you need if you want threads in Perl.
If you want threads to speed up your code when multiple cores are available, you are going down the wrong path. Perl is 50x slower than other languages. Rewriting your code to run on two CPUs means that it now only runs 25x slower than other languages ... on one CPU. Better to spend the effort porting the slow parts to a different language.
But if you just don't want IO to block other "threads", then Coro is exactly what you want.
Most recent versions of Perl have threading support. Run perl -V:usethreads
to see if it is available in your system.
$ perl -V:usethreads
usethreads='define'
perldoc threads gives a pretty good introduction to using them.
It sounds like you don't need preemptive multithreading; in which case, look at POE's cooperative model. Since your code will only yield to other threads when you decide, and you'll only have one thread running at a time, development and debugging will be much easier.
There are lots of reasons why you might not want to multithread. If you do want to multithread, however, the following code might serve as a helpful example. It creates a number of jobs, puts those in a thread-safe queue, then starts some threads that pull jobs from the queue and complete them. Each thread keeps pulling jobs from the queue in a loop until it sees no more jobs. The program waits for all the thread to finish and then prints the total time that it spent working on the jobs.
#!/usr/bin/perl
use threads;
use Thread::Queue;
use Modern::Perl;
my $queue= Thread::Queue->new;
my $thread_count= 4;
my $job_count= 10;
my $start_time= time;
my $max_job_time= 10;
# Come up with some jobs and put them in a thread-safe queue. Each job
# is a string with an id and a number of seconds to sleep. Jobs consist
# of sleeping for the specified number of seconds.
my @jobs= map {"$_," . (int(rand $max_job_time) + 1)} (1 .. $job_count);
$queue->enqueue(@jobs);
# List the jobs
say "Jobs IDs: ", join(", ", map {(split /,/, $_)[0]} @jobs);
# Start the threads
my @threads= map {threads->create(sub {function($_)})} (1 .. $thread_count);
# Wait for all the threads to complete their work
$_->join for (@threads);
# We're all done
say "All done! Total time: ", time - $start_time;
# Here's what each thread does. Each thread starts, then fetches jobs
# from the job queue until there are no more jobs in the queue. Then,
# the thread exists.
sub function {
my $thread_id= shift;
my ($job, $job_id, $seconds);
while($job= $queue->dequeue_nb) {
($job_id, $seconds)= split /,/, $job;
say "Thread $thread_id starting on job $job_id ",
"(job will take $seconds seconds).";
sleep $seconds;
say "Thread $thread_id done with job $job_id.";
}
say "No more jobs for thread $thread_id; thread exiting.";
}