Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: разработка для Web > Многопоточность и join


Автор: burakov 21.4.2011, 21:58
Вот пробный код с двумя потоками. Вопрос в следующем:
во все примерах про потоки  - join - это чтобы родительская программа дождалась, когда дочерние потоки выполнятся.
И всегда делают join на каждый запущенный поток.

Я если делаю join на каждый поток, то ниже идущий поток не выполняется , поэтому поток thread_worker2 приходится запускать - детач.
Это так и должно быть??  или я чего то не понимаю??


Код

my $thread_worker2 = threads -> new (\&thread_worker2);
my $thread_worker3 = threads -> new (\&thread_worker3) -> join ();

sub thread_worker2 {
    while (1) {
        print 1 ."\n"; 
        sleep 1; 
    }
    
}

sub thread_worker3 {
    while (1) {
        print 2 ."\n"; 
        sleep 2;
    }
}


Автор: DurRandir 21.4.2011, 22:30
Вы хоть этот код запускали?) Он работает ровно как написано - печатает в вечном цикле 2 разные цифры. Приводите реальный код.

Автор: Pfailed 22.4.2011, 07:38
Обычно сначала запускают все потоки, складывая их id в массив. А потом в цикле для каждого элемента массива делают join.

Автор: burakov 22.4.2011, 08:21
Я Вам про то же и говорю!

Код я реально запускал - он рабочий, потому что есть всего один join на самый последний поток. Если заджойнить все потоки, то будет выполняться самый верхний заджойненный. Я и спрашиваю почему так происходит?? поскольку как и Pfailed везде в примерах видел, что join делают на все потоки! (кто массив пропускает по foreach , если потоков много - штук 50 , ну а у меня всего 2 - я их вручную заджойнил).

Моя проблема  в том, что выполняется первый заджойненный, а остальные нет.
Тогда я Вышел из положения первому потоку дал детач, а последнему (в порядке появления в теле основной программы) сделал join и все заработало.

Я и решил спросить - такое поведение потоков нормально ?? Почему в примерах join делают на каждый поток, а мне приходится делать на последний? 

Автор: Pfailed 22.4.2011, 08:31
Потому что join нужно делать только после запуска всех потоков. Как в моем предыдущем сообщении
Код

# сперва всё запустить
push @threads, threads->new(...);
push @threads, threads->new(...);

# потом всё ждать
$_->join for @threads;


Автор: burakov 22.4.2011, 08:59
Да так работает, но тогда возникает вопрос 

как делать join, если количество потоков заранее неизвестно . Ну то есть допустим я хочу сделать количество потоков от 0 до 50. И каждый нужно заджойнить и неизвестно сколько потоков на данный момент времени существует... Догадываюсь что нужно сначала пройтись по всем - детач, а  потом добавить новый поток и опять все заджойнить? 

Автор: burakov 25.4.2011, 00:07
Подскажите в таком вопросе.
Как в многопоточном грабере сделать проверку на то, что все уже сграблено?
То есть грабер закончил работу? 

Я придумал, считать количество ссылок в таблице, куда записываю уникальные ссылки на скачивание контента, 
делаю в отдельном потоке sleep 10; и каждые 10 секунд проверяю количество записей в таблице ссылок, если количество в 2х проходах одинаково, значит ничего больше не добавляется и можно программу завершать, но как то мне самому такое завершение работы не очень нравится (а вдруг ссылки не добавляется, но скачка контента еще идет - допустим картинка большая).

Как еще можно понять работает грабер или уже ничего не делает?

Кроме того мои однопоточные граберы страдали такой болезнью - время от времени как бы подвисали, ну то есть выполняет get ($url) и все ни с места. Я так подозреваю, что сайты-доноры как то  обрубают коннект по времени или еще как, а грабер висит на моменте get($url) ... Как такое дело можно отследить и убить некорректный поток?


Автор: JamesMorgan 18.7.2011, 10:16
timeout выставить, если ответа нету то вернуть сообщение об этом.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)