2012-04-14 17 views
6

Projemde, bir istemciden iş istekleri alan bir Java yürütme çerçevesi yapıyorum. İş (değişken boyut), bir görevler kümesine ayrılır ve daha sonra işlenmek üzere sıraya alınır. Her görev türünü işlemek için ayrı sıralar vardır ve her sıra bir ThreadPool ile ilişkilendirilir. ThreadPools, motorun genel performansı optimal olacak şekilde yapılandırılmıştır.İş/Görev Çalma ThreadPoolExecutor

Bu tasarım, istekleri etkili bir şekilde dengelememize yardımcı olur ve büyük istekler, sistem kaynaklarını boşa çıkarmaya son vermez. Ancak, zaman zaman bazı kuyruklar boş olduğunda ve ilgili iplik havuzları boşta kaldığında çözüm etkisiz hale gelir.

Bunu daha iyi hale getirmek için, yoğun bir şekilde yüklenen kuyruğun diğer ThreadPools'lardan yardım alabilmesi için bir iş/görev çalma tekniğinin uygulanmasını düşünüyordum. Ancak bu, Java gibi kendi Executor'ımın uygulanmasını gerektirebilir, birden çok sıra bir ThreadPool ile ilişkilendirilmesine izin vermez ve çalışma çalma konseptini desteklemez.

Çatal/Katılma hakkında bilgi edinin; ancak bu, ihtiyaçlar için uygun görünmüyor. Bu çözümü oluşturmak için herhangi bir öneri veya alternatif bir yol çok yardımcı olabilir.

Teşekkür Andy

+1

Tüm CPU'larınızı nasıl meşgul edeceğinizi düşünmelisiniz. İşlemcinizden en iyi şekilde yararlanıyorsanız, bazı iplikleriniz boşta kalmaz. –

+0

İş parçacığı havuzlarınızda cpus adında çok sayıda iş parçacığı varsa, diğer iş parçacığı havuzları boşta olsa bile, herhangi bir iş parçacığı havuzu tüm cpus'u "çalabilir". –

+0

@PeterLawrey - bu doğru, ancak çok fazla havuz varsa, tüm havuzlardaki tüm dişler aynı anda çalışıyorsa, performansınız kötü olabilir. – jtahlborn

cevap

1

bir "birincil" kuyrukta ve 0 veya daha fazla ikincil kuyruklar tarafından desteklenmektedir özel BlockingQueue uygulama (i esas offer() ve take() yöntemleri uygulamak gerekir düşünüyorum) uygulayabilir. almak, boş olmayan ise her zaman birincil yedekleme kuyruğundan alacaktır, aksi takdirde ikincil sıralardan çekilebilir. Aslında, tüm çalışanların tüm kuyruklara erişebildiği ancak belirli bir kuyruğu "tercih ettiği" 1 havuza sahip olmak daha iyi olabilir. Farklı işçilere farklı öncelikler atayarak optimal iş oranınızı yakalayabilirsiniz. Tam yüklü bir sistemde, çalışanlarınız en uygun oranda çalışmalıdır. Düşük yüklü bir sistemde, çalışanlarınız diğer kuyruklarla yardım edebilmelidir.

+0

Bu, bir POC ile denemek için yaslandığım iyi bir fikir gibi görünüyor. –

2

ForkJoinPool'u düşündünüz mü? Çatal-birleştirici çerçeve güzel modüler bir şekilde uygulandı, böylece sadece iş-çalıyor iplik havuzunu kullanabilirsiniz.

+1

API'yi okuyun, ancak normal ThreadPoolExecutor'dan farklı bir şekilde nasıl olduğunu anlayamıyorsunuz. Belki orada bazı ince yönlerini eksik. –

+0

Evet, aslında sahip olduğunuz şey aslında esnek hale getirmek istediğiniz bir bölümleme şemasıdır - bölme sınırlarının iş yüküne göre değişmesine izin verin. “Çalmak çalmak”, iyi bir görev granülasyonu içeren şemalar için daha özel bir terim olabilir - bir iş parçacığı üzerinde çalışan bir görev alt görevleri oluşturur ve bunları kendi dezerine iter, böylece diğer iş parçacıkları işini çalabilir. Yani belki "iş parçacığı havuzu bölümleme" terimi ile araştırma yaparsanız, sizin durumunuza uygun bir şey bulacaksınız. –

2

Java 8, Executors sınıfında bunun için fabrika ve yardımcı program yöntemlerine sahiptir. Çalınan bir iş parçacığı havuzunun (here) bir uygulaması var;

+0

Sadece bununla ilgili dezavantaj, bu konuları global bir havuzdan ödünç almak yerine talep üzerine yeni ForkJoinThreads oluşturmasıdır - müşterinin geçebileceği ortak bir havuz veya havuz olabilir. –