Improvement

use strict;
use threads;
use Thread::Queue;

my $queue = new Thread::Queue;

my @threads;
foreach my $thread_no (1..$proc_num) {
  my $t = async {
      while (my ($test_params) = $queue->dequeue) {
          last unless $test_params;
          do_some_work(%$test_params);
      }
  };
  push @threads, $t;
}

$queue->enqueue(@tests);
map $queue->enqueue(undef), scalar @threads;
$_ && $_->join foreach @threads;