Saya mencoba menjalankan dua AsyncTasks secara bersamaan. (Platform adalah Android 1.5, HTC Hero.) Namun, hanya yang pertama yang dieksekusi. Berikut cuplikan sederhana untuk menjelaskan masalah saya:
public class AndroidJunk extends Activity {
class PrinterTask extends AsyncTask<String, Void, Void> {
protected Void doInBackground(String ... x) {
while (true) {
System.out.println(x[0]);
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new PrinterTask().execute("bar bar bar");
new PrinterTask().execute("foo foo foo");
System.out.println("onCreate() is done.");
}
}
Output yang saya harapkan adalah:
onCreate() is done.
bar bar bar
foo foo foo
bar bar bar
foo foo foo
Dan seterusnya. Namun, yang saya dapatkan adalah:
onCreate() is done.
bar bar bar
bar bar bar
bar bar bar
AsyncTask kedua tidak pernah dieksekusi. Jika saya mengubah urutan pernyataan execut (), hanya tugas foo yang akan menghasilkan output.
Apakah saya kehilangan sesuatu yang jelas di sini dan / atau melakukan sesuatu yang bodoh? Apakah tidak mungkin menjalankan dua AsyncTasks secara bersamaan?
Sunting: Saya menyadari telepon yang dipermasalahkan menjalankan Android 1.5, saya memperbarui masalah descr. demikian. Saya tidak punya masalah dengan HTC Hero yang menjalankan Android 2.1. Hmmm ...
Jawaban:
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:
DONUT adalah Android 1.6, HONEYCOMB adalah Android 3.0.
PEMBARUAN: 2
Lihat komentar dari
kabuko
dariMar 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 masukdoInBackground()
, 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 memasukkannyadoInBackground()
, 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 macetjava.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 mencegahAsyncTask
membuat terlalu banyak utas.Sebelum Android 4.4 (API 19)
AsyncTask
memiliki bidang-bidang berikut:Di Android 4.4 (API 19) bidang di atas diubah menjadi ini:
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.
sumber
AsyncTaskCompat.executeParallel(task, params);
AsyncTaskCompat.executeParallel(task, params);
sekarang sudah tidak digunakan lagiIni memungkinkan eksekusi paralel pada semua versi Android dengan API 4+ (Android 1.6+):
Ini ringkasan jawaban Arhimed yang luar biasa.
Pastikan Anda menggunakan API level 11 atau lebih tinggi sebagai target build proyek Anda. Dalam Eclipse, itu
Project > Properties > Android > Project Build Target
. Ini tidak akan merusak kompatibilitas ke belakang ke tingkat API yang lebih rendah. Jangan khawatir, Anda akan mendapatkan kesalahan Lint jika Anda secara tidak sengaja menggunakan fitur yang diperkenalkan paling lambatminSdkVersion
. Jika Anda benar-benar ingin menggunakan fitur diperkenalkan lambatminSdkVersion
, Anda dapat menekan kesalahan-kesalahan menggunakan penjelasan, tetapi dalam hal ini, Anda perlu berhati-hati tentang kompatibilitas sendiri . Inilah yang terjadi pada cuplikan kode di atas.sumber
void startMyTask(AsyncTask<Void, ?, ?> asyncTask)
(jika doInBackground Anda kosong)Membuat saran @sulai lebih umum:
sumber
Hanya untuk memasukkan pembaruan terbaru (PEMBARUAN 4) dalam jawaban rapi @Arhimed dalam ringkasan @sulai yang sangat baik:
sumber
.executeOnExecutor()
sekarang berlebihan untuk API> = KITKAT, ya?Contoh pengembang android memuat bitmap secara efisien menggunakan asynctask khusus (disalin dari jellybean) sehingga Anda dapat menggunakan executeOnExecutor di apis lebih rendah dari <11
http://developer.android.com/training/displaying-bitmaps/index.html
Unduh kode dan pergi ke paket util.
sumber
Itu mungkin. Versi perangkat android saya adalah 4.0.4 dan android.os.Build.VERSION.SDK_INT adalah 15
Saya punya 3 pemintal
Dan saya juga memiliki kelas Async-Tack.
Ini adalah kode pemuatan pemintal saya
Ini bekerja dengan sempurna. Satu per satu pemintal saya dimuat. Saya tidak pengguna mengeksekusi OnExecutor.
Ini kelas tugas Async saya
sumber
jika Anda ingin menjalankan tugas paralel, Anda perlu memanggil metode
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "your task name")
setelah Android versi 3.0; tetapi metode ini tidak ada sebelum Android 3.0 dan setelah 1.6 karena itu menjalankan paralel dengan sendirinya, Jadi saya sarankan Anda menyesuaikan kelas AsyncTask Anda sendiri dalam proyek Anda, untuk menghindari pengecualian melemparkan dalam versi Android yang berbeda.sumber