2012-04-14 17 views
6

W moim projekcie buduję framework wykonawczy Java, który odbiera żądania pracy od klienta. Praca (różna wielkość) jest podzielona na zestaw zadań, a następnie umieszczana w kolejce do przetwarzania. Istnieją osobne kolejki do przetwarzania każdego typu zadania, a każda kolejka jest powiązana z wątkiem. Zestawy ThreadPools są skonfigurowane w taki sposób, aby ogólna wydajność silnika była optymalna.Kradzież pracy/zadania ThreadPoolExecutor

Ten projekt pomaga nam efektywnie ładować żądania, a duże żądania nie kończą się na hakowaniu zasobów systemowych. Czasami jednak rozwiązanie staje się nieskuteczne, gdy niektóre z kolejek są puste, a ich pule wątków pozostają bezczynne.

Aby było to lepsze, zastanawiałem się nad wprowadzeniem techniki kradzieży pracy/zadania, tak aby mocno obciążona kolejka mogła uzyskać pomoc z innych pakietów ThreadPool. Może to jednak wymagać implementacji mojego Executora, ponieważ Java nie pozwala na powiązanie wielu kolejek z wątkiem ThreadPool i nie obsługuje koncepcji kradzieży pracy.

Przeczytaj o Fork/Join, ale to nie wydaje się pasować do moich potrzeb. Wszelkie sugestie lub alternatywny sposób na zbudowanie tego rozwiązania mogą być bardzo pomocne.

Dzięki Andy

+1

Powinieneś pomyśleć o tym, jak utrzymać wszystkie procesory zajęte. Nie ma znaczenia, czy niektóre wątki są bezczynne, jeśli optymalnie wykorzystujesz procesory. –

+0

Jeśli pule wątków mają tyle wątków, co cpus, każda pojedyncza pula wątków może "ukraść" wszystkie procesory, nawet jeśli wszystkie pozostałe pule wątków są bezczynne. –

+0

@PeterLawrey - to prawda, ale w przypadku dużej ilości pul można mieć słabą wydajność, jeśli wszystkie wątki we wszystkich pulach działają w tym samym czasie. – jtahlborn

Odpowiedz

1

można realizować wdrożenie niestandardowych BlockingQueue (myślę, że przede wszystkim należy wdrożyć metody offer() i take()), który jest wspierany przez „pierwotnym” kolejki i 0 lub więcej drugorzędnych kolejek. weź zawsze bierze od głównej kolejki, jeśli nie jest pusta, w przeciwnym razie może pobierać z kolejek drugorzędnych.

w rzeczywistości może być lepiej mieć 1 pulę, w której wszyscy pracownicy mają dostęp do wszystkich kolejek, ale "preferują" określoną kolejkę. możesz uzyskać optymalny stosunek pracy, przypisując różne priorytety różnym pracownikom. w pełni obciążonym systemie pracownicy powinni pracować w optymalnym stosunku. w niedociążonym systemie twoi pracownicy powinni być w stanie pomóc innym koleżankom.

+0

To wydaje się być dobrym pomysłem, który próbuję wypróbować z POC. –

2

Czy brałeś pod uwagę ForkJoinPool? Struktura łączenia widełek została zaimplementowana w ładny modułowy sposób, więc można po prostu użyć kradzieży wątków.

+1

Przeczytaj API, ale wciąż nie możesz zrozumieć, jak różni się on od zwykłego ThreadPoolExecutor. Być może brakuje tam pewnych drobniejszych aspektów. –

+0

Tak Widzę, to, co masz, to schemat partycjonowania, który chcesz teraz uczynić elastycznym - pozwól, aby granice partycji przesuwały się zgodnie z obciążeniem. "Kradzież pracy" może być bardziej wyspecjalizowanym terminem dla schematów, które wymagają drobnej granulacji zadań - zadanie wykonywane w jednym wątku generuje podzadania i przesuwa je do własnej pamięci, aby inne wątki mogły ukraść jej pracę. Może więc, jeśli przeprowadzisz badania według terminu "partycjonowanie puli wątków", znajdziesz coś odpowiedniego dla twojej sprawy. –

2

Java 8 ma metody fabryczne i narzędzie do tego w klasie Executors. Istnieje implementacja kradzieży wątków roboczych (here), która, jak sądzę, jest dokładnie tym, czego potrzebujesz.

+0

Jedyną wadą, jaką widzę, jest to, że tworzy nowe ForkJoinThreads na żądanie zamiast pożyczać te wątki z globalnej puli - może to być wspólna pula lub pula, którą może przekazać klient. –

Powiązane problemy