AsyncTask menggunakan pola kumpulan thread untuk menjalankan hal-hal dari doInBackground (). Masalahnya awalnya (dalam versi OS Android awal) ukuran kolam hanya 1, yang berarti tidak ada perhitungan paralel untuk sekelompok AsyncTasks. Tetapi kemudian mereka memperbaikinya dan sekarang ukurannya 5, sehingga paling banyak 5 AsyncTasks dapat berjalan secara bersamaan. Sayangnya saya tidak ingat dalam versi apa tepatnya mereka mengubahnya.
MEMPERBARUI:
Inilah yang dikatakan API (2012-01-27) terkini tentang ini:
Ketika pertama kali diperkenalkan, AsyncTasks dieksekusi secara serial pada utas latar belakang tunggal. Dimulai dengan DONUT, ini diubah menjadi kumpulan untaian yang memungkinkan beberapa tugas beroperasi secara paralel. Setelah HONEYCOMB, direncanakan untuk mengubah ini kembali ke utas tunggal untuk menghindari kesalahan aplikasi umum yang disebabkan oleh eksekusi paralel. Jika Anda benar-benar ingin eksekusi paralel, Anda dapat menggunakan versi executeOnExecutor (Executor, Params ...) dari metode ini dengan THREAD_POOL_EXECUTOR; Namun, lihat komentar di sana untuk peringatan tentang penggunaannya.
DONUT adalah Android 1.6, HONEYCOMB adalah Android 3.0.
PEMBARUAN: 2
Lihat komentar dari kabuko
dari Mar 7 2012 at 1:27
.
Ternyata untuk API di mana "kumpulan thread yang memungkinkan beberapa tugas untuk beroperasi secara paralel" digunakan (mulai dari 1,6 dan berakhir pada 3,0) jumlah menjalankan AsyncTasks secara bersamaan tergantung pada berapa banyak tugas yang telah dilewati untuk dieksekusi, tetapi belum selesai doInBackground()
.
Ini diuji / dikonfirmasi oleh saya di 2.2. Misalkan Anda memiliki AsyncTask khusus yang hanya memerlukan waktu satu detik doInBackground()
. AsyncTasks menggunakan antrian ukuran tetap secara internal untuk menyimpan tugas yang tertunda. Ukuran antrian adalah 10 secara default. Jika Anda memulai 15 tugas kustom Anda secara berturut-turut, maka 5 tugas pertama akan masuk doInBackground()
, tetapi sisanya akan menunggu dalam antrian untuk utas pekerja gratis. Segera setelah salah satu dari 5 yang pertama selesai, dan dengan demikian melepaskan utas pekerja, tugas dari antrian akan memulai eksekusi. Jadi dalam hal ini paling banyak 5 tugas akan berjalan secara bersamaan. Namun jika Anda memulai 16 tugas kustom Anda secara berturut-turut, maka 5 pertama akan memasukkannya doInBackground()
, sisanya 10 akan masuk ke dalam antrian, tetapi untuk ke-16 utas pekerja baru akan dibuat sehingga akan segera memulai eksekusi. Jadi dalam hal ini paling banyak 6 tugas akan berjalan secara bersamaan.
Ada batasan berapa banyak tugas yang dapat dijalankan secara bersamaan. Karena AsyncTask
menggunakan pelaksana kumpulan thread dengan jumlah maksimal utas pekerja (128) dan antrian tugas yang tertunda memiliki ukuran 10, jika Anda mencoba menjalankan lebih dari 138 tugas khusus, aplikasi akan macet java.util.concurrent.RejectedExecutionException
.
Mulai dari 3.0, API memungkinkan untuk menggunakan pelaksana kumpulan thread khusus Anda melalui AsyncTask.executeOnExecutor(Executor exec, Params... params)
metode. Ini memungkinkan, misalnya, untuk mengkonfigurasi ukuran antrian tugas yang tertunda jika default 10 bukan yang Anda butuhkan.
Seperti @Knossos menyebutkan, ada opsi untuk digunakan AsyncTaskCompat.executeParallel(task, params);
dari pustaka dukungan v.4 untuk menjalankan tugas secara paralel tanpa repot dengan level API. Metode ini menjadi usang di API level 26.0.0.
PEMBARUAN: 3
Berikut ini adalah aplikasi pengujian sederhana untuk bermain dengan sejumlah tugas, eksekusi serial vs paralel: https://github.com/vitkhudenko/test_asynctask
UPDATE: 4 (terima kasih @penkzhou untuk menunjukkan ini)
Mulai dari Android 4.4 AsyncTask
berperilaku berbeda dari apa yang dijelaskan dalam bagian UPDATE: 2 . Ada perbaikan untuk mencegah AsyncTask
membuat terlalu banyak utas.
Sebelum Android 4.4 (API 19) AsyncTask
memiliki bidang-bidang berikut:
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);
Di Android 4.4 (API 19) bidang di atas diubah menjadi ini:
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);
Perubahan ini meningkatkan ukuran antrian menjadi 128 item dan mengurangi jumlah utas maksimum menjadi jumlah inti CPU * 2 + 1. Aplikasi masih dapat mengirimkan jumlah tugas yang sama.