Strategia sterowania wątkami

0

Mam od ponad dnia zagwozdkę i nigdzie nie mogę znaleźć odpowiedzi.
Chodzi o obsługę wątków w programie typu downloader wielkiej liczby małych plików txt.
Generalnie wszystko działa, tylko z rozdzieleniem na 2 wątki - widok i logikę. Chciałem zrobić tak, aby jednocześnie było uruchomionych mniej więcej non stop 10 wątków pobierających.
Stworzyłem sobie tablicę Threadów, zdefiniowałem klasę downloadera jako Runnable i generalnie wszystko było na dobrej drodze, aż się zatrzymałem na ścianie.
Bez problemu uruchamia się 10 wątków i wszystko się ładnie pobiera, ale jak teraz obsłużyć to, że gdy jeden wątek kończy pracę, to automatycznie tworzony i uruchamiany jest nowy (z kolejnym id pliku do pobrania, czyli id+10). Myślałem o jakimś obserwatorze, ale nigdzie nie mogę znaleźć, żeby ktoś to stosował. Wszędzie są tylko przykłady z join(), ale w tym przypadku nie o to chodzi. Sprawdzanie w pętli co chwilę isAlive() na każdym wątku to chyba też nieporozumienie. Próbowałem sterowania wyjątkami, ale też bez sukcesu.
Ktoś mnie może naprowadzić na dobrą drogę, jest może od tego jakiś wzorzec?

0

Hmm ja to mam rozwiązane w ten sposób, że posiadam swoją magiczną klasę, która to obsługuje mi kolejkowanie.
Głowny program zgłasza plik do pobrania, ten jest wstawiany do kolejki. Arbiter startuje watki dopóki liczba ich nie osiągnie mojego tam limitu (użytkownik to w opcjach po prostu ustawia). Wątek po zakończeniu przed zakończeniem żywota ustawia sobie odpowiednią flagę i zgłasza zmianę statusu do arbitra. Ten natomiast wywala wątek z kolejki a na jego miejsce wstawia kolejny z kolejki i go startuje. Działa czarująco. Sprawdź sam www.toptraker.pl - odpal soft, otwórz dowolną listę (zobaczysz o co chodzi) i kliknij pobierz wszystko :)

0

Twoja ściana została niedawno systemowo rozwiązana.
Za utrzymywanie stałej puli wątków wykonujących nieograniczoną liczbę zadań odpowiada w Javie 7 nowa klasa ForkJoinPool.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ForkJoinPool.html
Każdy wątek, który zakończy przetwarzanie będzie "podkradał" i wykonywał następne zadanie z puli, aż do ich wyczerpania.
Jest ona szczególnie przydatna jeżeli liczbę wątków ustawimy na Runtime.getRuntime().availableProcessors() - 1, o ile są przynajmniej dwa bo wtedy wszystkie nadmiarowe procesory (rdzenie) będą wykorzystywane do maksimum.

Polecam przewalić javadoca i nauczyć się ją wykorzystywać bo naprawdę warto.
http://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html

ps. Przy okazji Twoim wąskim gardłem stanie się wtedy nie przetwarzanie wczytanych plików, ale raczej samo ich wczytywanie.
W tym wypadku warto skorzystać z innej nowości w Javie 7 czyli klasy FileChannel (oderwanej wreszcie od strumieni), po to aby każdy plik był wczytywany za jednym zamachem do bufora o wielkości całego pliku (przynajmniej dopóki jest mniejszy niż ćwierć całej dostępnej pamięci w Javie: (maxMemory - totalMemory + freMemory) /4). Przy okazji bardzo przyspiesza to dekodowanie bufora bajtowego jeżeli pliki txt nie są w UTF-16BE.
Wtedy wczytywanie i przetwarzanie liczby plików rzędu kilkuset tysięcy sztuk robi się migiem.

0

Dzięki za odpowiedzi, szczególnie Olamagato - bardzo ciekawe informacje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1