Исходя из данного метода я делаю на основе примера:
#!/usr/bin/perl -w
use threads;
# В этом массиве будут храниться ссылки на
# созданные нити
my @threads;
# Создаём 3 нити в режиме по прниципу "создал и забыл", тем
# самым позволив открыть параллельно несколько нитей. Объект
# каждой созданной нити помещается в массив @threads
for my $i (1..3) {
push @threads, threads->create(\&get_now, $i);
}
# Нити успешно созданы, ссылки на объекты помещены в массив
# Теперь мы можем для каждого объекта вызвать метод join(),
# заставляющий интерпретатор ожидать завершение работы треда.
foreach my $thread (@threads) {
# Обратите внимание, что $thread является не объектом, а ссылкой,
# поэтому управление ему передано не будет.
$thread->join();
}
sub get_now
{
my $num = shift;
print "thread ", $num, " => ", time(), "\n";
sleep 1;
}
Т.е., при каждом добавлении:
* проходить весь массив @threads, искать завершенные треды (надо ещё узнать, как)
* удалять завершенные
* проверять размер массива, и если там меньше элементов - добавить новый тред, если он заполнен по максимум - подождать секунду и повторить.
Подход неверный.
Верный подход:
Создать сколько нужно тредов и распределять между ними задания. Когда какой-то из тредов закончит работу он возьмет новую пачку заданий. Если заданий не будет то завершится.
Слушай, это ж гениально! Создать n тредов, в которых будет организован цикл. Каждый тред в каждой итерации цикла будет брать некие данные из предварительно сформированного списка (pop), и если данные закончатся - тред завершается.
Это поразительно просто!
//Треды используются для параллельного запуска нескольких копий системной утилиты ping.
Надеюсь, использование pop в списках в Perl - thread-safe.
//Треды используются для параллельного запуска нескольких копий системной утилиты ping.
Вдвойне сомнительно использовать для этого треды.
Знакомы с событийными машинами в Perl? Есть модуль AnyEvent::FastPing. Позволит вам пинговать множество хоство в рамках одного процесса параллельно (без создания потоков).
Если всё же хочется использовать утилиту ping. Вы вероятно как-то так хотите её запускать: $response = `ping -c 5 host`. И так в каждом потоке. Это неправильный вариант.
Правильный вариант:
perldoc -f open. Ф-ция open умеет запускать указанную внешнюю программу и устанавливать канал между запущенной программой и вашим процессом. Таким образом вест STDOUT запущенной программы будет доступен через дескриптор файла. Итого: открываем сколько нужно утилит ping и в цикле используя select() чтобы определить дескрипторы доступные для чтения получаем ответы.
Кроме ping необходимо ещё пускать самописную утилиту, тоже параллельно.
Вы вероятно как-то так хотите её запускать: $response = `ping -c 5 host`. И так в каждом потоке. Это неправильный вариант.
А можно узнать, почему? Разве команды не запускаются параллельно в таком случае?
perldoc -f open. Ф-ция open умеет запускать указанную внешнюю программу и устанавливать канал между запущенной программой и вашим процессом. Таким образом вест STDOUT запущенной программы будет доступен через дескриптор файла. Итого: открываем сколько нужно утилит ping и в цикле используя select() чтобы определить дескрипторы доступные для чтения получаем ответы.