RxJava zamanlayıcılar için kullanım örnekleri


253

RxJava'da seçim yapabileceğiniz 5 farklı zamanlayıcı vardır :

  1. instant () : Geçerli iş parçacığında hemen çalışma yürüten bir Zamanlayıcı oluşturur ve döndürür.

  2. trampoline () : Geçerli iş tamamlandıktan sonra yürütülecek geçerli iş parçacığında kuyrukları çalıştıran bir Zamanlayıcı oluşturur ve döndürür.

  3. newThread () : Her iş birimi için yeni bir İş Parçacığı oluşturan bir Zamanlayıcı oluşturur ve döndürür.

  4. computation () : Hesaplamalı çalışmaya yönelik bir Zamanlayıcı oluşturur ve döndürür. Bu, olay döngüleri, geri aramaların işlenmesi ve diğer hesaplama işleri için kullanılabilir. Bu zamanlayıcıda GÇ bağlı işleri yapmayın. Zamanlayıcıları kullanın. yerine io () .

  5. io () : G / Ç ile ilişkili işler için tasarlanmış bir Zamanlayıcı oluşturur ve döndürür. Uygulama, gerektiğinde büyüyecek bir Execut iş parçacığı havuzu tarafından desteklenir. Bu, eşzamansız olarak bloke edici ES'yi gerçekleştirmek için kullanılabilir. Bu zamanlayıcı üzerinde hesaplama çalışması yapmayın. Zamanlayıcıları kullanın. computation () yerine.

Sorular:

İlk 3 zamanlayıcı oldukça açıklayıcıdır; ancak, hesaplama ve io hakkında biraz kafam karıştı .

  1. "ES'ye bağlı çalışma" tam olarak nedir? Streams ( java.io) ve files ( java.nio.files) ile uğraşmak için kullanılıyor mu? Veritabanı sorguları için kullanılıyor mu? Dosyaları indirmek veya REST API'lerine erişmek için kullanılıyor mu?
  2. Nasıl hesaplama () farklıdır newThread () ? Tüm computation () çağrıları her seferinde yeni (arka plan) bir iş parçacığı yerine tek (arka plan) iş parçacığında mıdır?
  3. IO çalışması yaparken computation () öğesini çağırmak neden kötü ?
  4. Hesaplamalı iş yaparken io () öğesini çağırmak neden kötü ?

Yanıtlar:


332

Harika sorular, belgelerin biraz daha ayrıntılı yapabileceğini düşünüyorum.

  1. io()sınırsız bir iş parçacığı havuzu tarafından desteklenir ve hesaplama açısından yoğun olmayan görevler için kullanacağınız bir şeydir, yani CPU'ya fazla yük getirmeyen şeylerdir. Bu yüzden dosya sistemi ile etkileşim, farklı bir ana bilgisayardaki veritabanları veya hizmetler ile etkileşim iyi örneklerdir.
  2. computation()kullanılabilir işlemci sayısına eşit büyüklükte sınırlı bir iş parçacığı havuzu ile desteklenir. CPU yoğun çalışmasını mevcut işlemcilerden daha fazla paralel olarak planlamaya çalıştıysanız (diyelim ki newThread()), bir işlemci için iş parçacıkları vie olarak iş parçacığı oluşturma yükü ve bağlam değiştirme yükü için hazırsınız ve bu muhtemelen büyük bir performans isabeti.
  3. computation()CPU yoğun iş için ayrılmak en iyisidir, aksi takdirde iyi CPU kullanımı elde edemezsiniz.
  4. io()2. io()bölümünde tartışılan nedenden dolayı hesaplama çalışması için kötü bir şeydir ve buna io()paralel olarak bin hesaplama görevi zamanlarsanız, bu bin görevin her birinin kendi iş parçacığı olacaktır ve CPU ile ilgili bağlam değiştirme maliyetleri için rekabet edecektir.

5
RxJava kaynağına aşinalık sayesinde. Uzun zamandır benim için bir karışıklık kaynağıydı ve bence belgelerin bu konuda güçlendirilmesi gerekiyor.
Dave Moten

2
@IgorGanapolsky Sanırım bu nadiren yapmak isteyeceğiniz bir şey. Her iş birimi için yeni bir iplik oluşturmak nadiren verimliliğe yol açar, çünkü ipliklerin inşası ve parçalanması pahalıdır. Genellikle computation () ve diğer zamanlayıcıların yaptığı iş parçacıklarını yeniden kullanmak istersiniz. NewThread () 'in meşru kullanımı olabileceği tek zaman (en azından düşünebileceğim), izole, seyrek, uzun süren görevleri başlatmaktır. O zaman bile bu senaryo için io () kullanabilirim.
tmn

4
Trambolin () 'in yararlı olacağı bir örnek gösterebilir misiniz? Kavramı anlıyorum ama pratikte kullanacağım bir senaryo bulamıyorum. Bana hala bir gizem olan tek zamanlayıcı
tmn

32
Ağ çağrıları için Schedulers.io () kullanın ve eşzamanlı ağ çağrılarının sayısını sınırlamanız gerekiyorsa Scheduler.from (Executors.newFixedThreadPool (n)) kullanın.
Dave Moten

4
timeoutVarsayılan olarak computation()size koymak bir iş parçacığını engelliyor olabilir, ancak durum böyle değil. Kapakları altında computation()bir kullanır ScheduledExecutorServicegecikmiş eylemleri engellemeyecek şekilde zaman. Bu gerçek computation()iyi bir fikir göz önüne alındığında , çünkü başka bir iş parçacığında olsaydı, iplik değiştirme maliyetlerine tabi oluruz.
Dave Moten

3

En önemli nokta hem olmasıdır Schedulers.io ve Schedulers.computation sorudaki diğerlerine karşı sınırsız iplik havuzları ile desteklenmektedir. Bu özellik yalnızca , Executor'un newCachedThreadPool (otomatik geri kazanma iş parçacığı havuzu ile sınırlandırılmamış) ile oluşturulması durumunda Schedulers.from (Executor) tarafından paylaşılır .

Önceki yanıtlarda ve web'deki birden çok makalede bolca açıklandığı gibi, Schedulers.io ve Schedulers.computation , isimlerindeki iş türü için optimize edildiğinden dikkatli bir şekilde kullanılmalıdır. Benim görüşüme göre, en önemli rol reaktif akışlara gerçek eşzamanlılık sağlamaktır .

Yeni gelenlerin inancının aksine, reaktif akışlar doğal olarak eşzamanlı değil, doğal olarak eşzamansız ve ardışıktır. Bu nedenle, Schedulers.io yalnızca G / Ç işlemi engellenirken kullanılmalıdır (örn: Apache IOUtils FileUtils.readFileAsString (...) gibi bir engelleme komutu kullanarak ), böylece işlem iş parçacığı yapılır.

Java AsynchronousFileChannel (...) gibi eşzamansız bir yöntem kullanmak, işlem sırasında çağıran iş parçacığını engellemez, bu nedenle ayrı bir iş parçacığı kullanmanın bir anlamı yoktur. Aslında, Schedulers.io iş parçacıkları, bir olay döngüsü çalıştırmadıklarından ve geri çağırma hiçbir zaman çağrılmadığından, eşzamansız işlemler için gerçekten uygun değildir.

Aynı mantık veritabanı erişimi veya uzak API çağrıları için de geçerlidir. Schedulers.io kullanma Sesli aramayı yapmak için bir zaman uyumsuz veya reaktif API kullanmak eğer.

Eşzamanlılığa geri dön. G / Ç işlemlerini eşzamansız veya eşzamanlı olarak yapmak için eşzamansız veya reaktif bir API'ye erişiminiz olmayabilir, bu nedenle tek alternatifiniz ayrı bir iş parçacığına birden fazla çağrı göndermektir. Ne yazık ki, Reaktif akışları uçlarında sıralı olan ama iyi haber olmasıdır flatMap () operatörü kendi özünde eşzamanlılık tanıtabilirsiniz .

Eşzamanlılık, genellikle flatMap () operatörü kullanılarak akış yapısında oluşturulmalıdır . Bu güçlü operatör, flatMap () katıştırılmış İşlev <T, R> için dahili olarak çok iş parçacıklı bir bağlam sağlamak üzere yapılandırılabilir . Bu bağlam, Scheduler.io veya Scheduler.computation gibi çok iş parçacıklı bir Zamanlayıcı tarafından sağlanır. .

Kod örneği ve Zamanlayıcıların sıralı ve eşzamanlı olarak nasıl kullanılacağı hakkında ayrıntılı açıklamalar bulabileceğiniz RxJava2 Zamanlayıcılar ve Eşzamanlılık ile ilgili makalelerde daha fazla ayrıntı bulabilirsiniz.

Bu yardımcı olur umarım,

Softjake


2

Bu blog yazısı mükemmel bir cevap veriyor

Blog gönderisinden:

Schedulers.io () , sınırsız bir iş parçacığı havuzu tarafından desteklenir. Dosya sistemi ile etkileşim, ağ çağrıları, veritabanı etkileşimleri vb. Gibi CPU-yoğun olmayan G / Ç tipi işler için kullanılır. Bu iş parçacığı havuzu, eşzamansız olarak engelleme G / Ç gerçekleştirmek için kullanılır.

Schedulers.computation () , kullanılabilir işlemcilerin sayısına kadar büyüklükte sınırlı bir iş parçacığı havuzu tarafından desteklenir. Görüntüleri yeniden boyutlandırma, büyük veri kümelerini işleme, vb. Gibi hesaplama veya CPU yoğun işlerde kullanılır. Dikkatli olun: kullanılabilir çekirdeklerden daha fazla hesaplama iş parçacığı ayırdığınızda, iş parçacığı geçişi olarak bağlam değiştirme ve iş parçacığı oluşturma yükü nedeniyle performans düşecektir işlemcilerin zamanı.

Schedulers.newThread () , zamanlanan her iş birimi için yeni bir iş parçacığı oluşturur. Bu zamanlayıcı pahalıdır, çünkü her seferinde yeni bir iş parçacığı ortaya çıkar ve yeniden kullanım gerçekleşmez.

Schedulers.from (Yürütücü yürütücüsü) , belirtilen yürütücü tarafından desteklenen özel bir zamanlayıcı oluşturur ve döndürür. İş parçacığı havuzundaki eşzamanlı iş parçacığı sayısını sınırlamak için Scheduler.from (Execrators.newFixedThreadPool (n)) kullanın. Bu, tüm iş parçacıkları işgal edildiğinde bir görev zamanlanırsa kuyruğa alınacağını garanti eder. Havuzdaki iş parçacıkları, açıkça kapatılana kadar varolur.

Ana iş parçacığı veya AndroidSchedulers.mainThread () , RxAndroid uzantı kitaplığı tarafından RxJava'ya sağlanır. Ana iş parçacığı (UI iş parçacığı olarak da bilinir) kullanıcı etkileşiminin gerçekleştiği yerdir. Önemsiz yanıtsız kullanıcı arayüzünü veya daha da kötüsü, Uygulama Yanıt Vermiyor ”(ANR) iletişim kutusunu önlemek için bu iş parçacığının aşırı yüklenmemesine dikkat edilmelidir.

Schedulers.single () , RxJava 2'de yenidir. Bu zamanlayıcı, görevleri istenen sırada sırayla yürüten tek bir iş parçacığı tarafından desteklenir.

Schedulers.trampoline () görevleri, katılımcı işçi iş parçacıklarından biri tarafından FIFO (İlk Giren, İlk Çıkar) biçiminde yürütür. Genellikle çağrı yığını büyümesini önlemek için özyineleme uygulanırken kullanılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.