AsyncTask, öğeleri doInBackground () öğesinden çalıştırmak için bir iş parçacığı havuzu deseni kullanır. Sorun başlangıçta (erken Android işletim sistemi sürümlerinde) havuz boyutu sadece 1 idi, bu da bir grup AsyncTasks için paralel hesaplamalar olmadığı anlamına geliyor. Ancak daha sonra bunu düzelttiler ve şimdi boyut 5, bu yüzden en fazla 5 AsyncTasks aynı anda çalışabilir. Ne yazık ki tam olarak hangi versiyonda bunu değiştirdiklerini hatırlamıyorum.
GÜNCELLEME:
Mevcut (2012-01-27) API'sı bu konuda şunları söylüyor:
İlk tanıtıldığında, AsyncTasks tek bir arka plan iş parçacığında seri olarak yürütüldü. DONUT ile başlayarak, bu, birden fazla görevin paralel olarak çalışmasına izin veren bir iş parçacığı havuzuna değiştirildi. HONEYCOMB sonrasında, paralel yürütmeden kaynaklanan yaygın uygulama hatalarından kaçınmak için bunu tek bir iş parçacığına geri döndürmek planlanmaktadır. Gerçekten paralel yürütme istiyorsanız, bu yöntemin executeOnExecutor (Executor, Params ...) sürümünü THREAD_POOL_EXECUTOR; ancak, kullanımıyla ilgili uyarılar için oradaki açıklamaya bakınız.
DONUT Android 1.6, HONEYCOMB Android 3.0'dır.
GÜNCELLEME: 2
Tarafından yoruma bakın kabuko
dan Mar 7 2012 at 1:27
.
"Birden fazla görevin paralel olarak çalışmasına izin veren bir iş parçacığı havuzunun" kullanıldığı (1.6'dan başlayıp 3.0'da biten) API'larda, eşzamanlı olarak çalışan AsyncTasks sayısının, yürütme için zaten kaç görevin geçtiğine bağlı olduğu ortaya çıkar, ancak henüz bitirmediler doInBackground()
.
Bu benim tarafımdan 2.2'de test edildi / onaylandı. Bir saniye içinde uyuyan özel bir AsyncTask'ınız olduğunu varsayalım doInBackground()
. AsyncTasks, gecikmeli görevleri depolamak için dahili olarak sabit boyutlu bir kuyruk kullanır. Kuyruk boyutu varsayılan olarak 10'dur. Özel görevlerinizi arka arkaya 15 olarak başlatırsanız, ilk 5 görevlerini girecek doInBackground()
, ancak geri kalanı ücretsiz bir işçi iş parçacığı için kuyrukta bekleyecektir. İlk 5 işlemden herhangi biri biter ve böylece bir işçi iş parçacığını serbest bırakır bırakmaz, kuyruktaki bir görev yürütülmeye başlar. Bu durumda, en fazla 5 görev aynı anda çalışır. Bununla birlikte, özel görevlerinizi arka arkaya 16 olarak başlatırsanız, ilk 5 tanesi bunlara girecek doInBackground()
, geri kalan 10 sıraya girecek, ancak 16'ncı için yeni bir iş parçacığı oluşturulacak, böylece hemen yürütmeye başlayacak. Bu durumda, en fazla 6 görev aynı anda çalışır.
Aynı anda kaç görevin çalıştırılabileceğinin bir sınırı vardır. Yana AsyncTask
kullanımlar çalışan iş parçacığı (128) ile kilitlenmesine fazla 138 özel görevleri uygulaması yürütmek çalışırsanız kuyruğu, boyutu 10 belirlemiştir gecikmiş görevlerin sınırlı maksimum sayı ile bir iş parçacığı havuzu vasisi java.util.concurrent.RejectedExecutionException
.
3.0'dan başlayarak API, özel iş parçacığı havuzu yürütücünüzü AsyncTask.executeOnExecutor(Executor exec, Params... params)
yöntemle kullanmanızı sağlar. Bu, örneğin, varsayılan 10 ihtiyacınız olan şey değilse, gecikmiş görev kuyruğunun boyutunu yapılandırmanıza izin verir.
@Knossos'un belirttiği gibi, AsyncTaskCompat.executeParallel(task, params);
destek v.4 kitaplığından API düzeyi ile uğraşmadan görevleri paralel olarak çalıştırmak için bir seçenek vardır . Bu yöntem API seviyesi 26.0.0'da kullanımdan kaldırıldı.
GÜNCELLEME: 3
İşte seri veya paralel yürütme ile görevlerin sayısı ile oynamak için basit bir test uygulaması: https://github.com/vitkhudenko/test_asynctask
GÜNCELLEME: 4 (bunu işaret ettiğiniz için @penkzhou teşekkürler)
Android 4.4'ten başlayarak, GÜNCELLEME: 2 bölümünde AsyncTask
açıklanandan farklı davranır . Çok fazla iş parçacığı oluşturmayı önlemek için bir düzeltme var .AsyncTask
Android 4.4'ten önce (API 19) AsyncTask
aşağıdaki alanlar vardı:
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);
Android 4.4'te (API 19) yukarıdaki alanlar şu şekilde değiştirilmiştir:
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
Bu değişiklik, kuyruğun boyutunu 128 öğeye çıkarır ve CPU çekirdeği sayısının maksimum iş parçacığı sayısını azaltır * 2 + 1. Uygulamalar yine de aynı sayıda görev gönderebilir.