複数動作AsyncTasks同時不可能でしょうか?
-
28-09-2019 - |
質問
ようにしている二つのAsyncTasksでも同時に行います。プラットフォームはAndroid1.5、HTCヒーローがあります。) しかし、最初のが実行されます。このシンプルなスニペットを記述する私の問題:
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.");
}
}
出力に期待したいです:
onCreate() is done.
bar bar bar
foo foo foo
bar bar bar
foo foo foo
います。しかし、私を取り付ける際に使用します。:
onCreate() is done.
bar bar bar
bar bar bar
bar bar bar
第AsyncTaskなが実行されます。を変更した場合、購入したのは、execute()諸表のみをfooタを出力します。
私を見落とさないようなことはやろうという愚かな?できないのですか二つのAsyncTasks同時にできますか。
編集:この電話での問題行Android1.5、更新の問題descr.ます。んが、この問題は、HTCのヒーロー走Android2.1.う~ん...
解決
AsyncTask用スレッドプールパターンを実行するためのものからdoInBackground().問題は、当初(早めのAndroid OSのバージョン)のプールサイズしただけ1とな並列計算のためのバAsyncTasks.その後も固定すると現在のサイズは5では最大5AsyncTasksです。残念ながらった記憶がないんですように版を正確に変えます。
更新:
ここでは電流(2012-01-27)APIということ:
最初に導入され、AsyncTasksが処刑された直列は、単一のバックグラウンねじになります。からドーナッツ、プールのスレッドを複数の操作を行なった。後ハニカムを行うことを計画して変更を単一のスレッドを避ける共通のアプリケーションエラーが発生による並列実行します。したければ並列実行に利用できますexecuteOnExecutor(往Params...バージョンのこのメソッドをTHREAD_POOL_EXECUTOR;しかし、解説が警告を利用します。
ドーナツはAndroid1.6カンパニーはAndroid3.0です。
更新:2
のコメント kabuko
から Mar 7 at 1:27
.
ここで示されているデータのためのApiが"プールのスレッドは、複数のタスクを並行して稼働"の利用開始から1.6期3.0)の数を同時に実行AsyncTasksに依存して多くの課題がっていたために実行がない終了 doInBackground()
ていない。
この試験により確認している私2.2となります。いカスタムAsyncTaskるだけで涼二 doInBackground()
.AsyncTasks固定サイズのキュー内部での保存が遅れます。キューサイズは10によるデフォルトです。合開始15カスタム作業を連続して第5に入その doInBackground()
, ものの、残りのままでお待ちキューにhttp応答ヘッダのみが書き換えられます。次のいずれかとして第5の終了まで、このリリース作業者のスレッドは、タスクキューから始まります。この場合は最大で5つの課題を実行す。ただし、16カスタム作業を連続して第5に入その doInBackground()
, 探しも、予約も、支払も、全部で10のままのキューが第16回新たに労働者のスレッドが作成されることがはいでしょう。実行を開始ます。このような場合でも6作業ます。
限界があるのかに多くの課題を走行可能。以降 AsyncTask
使用スレッドプールexecutor限られた最大数のワーカスレッド(128)の遅延タスクキュー固定サイズ10日にしようとした場合に実行以138カスタムタスクは、プロッジ java.util.concurrent.RejectedExecutionException
.
開始から3.0のAPIを使用できるよムスレッドプールexecutorによ AsyncTask.executeOnExecutor(Executor exec, Params... params)
方法。これにより、インスタンスは、設定サイズの遅延タスクキューの場合はデフォルトは10ではないで作られています。
として@クノッソスに言及しているオプションがあり利用 AsyncTaskCompat.executeParallel(task, params);
からの支援v.4図書館で実行並列タスクの手を煩わせることなくAPIです。このメソッドは非推奨となり、APIレベルの26.0.0.
更新:3
ここでは、簡単な試験アプリの遊びの数のタスク、シリアルvsルチコアcpuを生かして並列実行: https://github.com/vitkhudenko/test_asynctask
更新:4 (感謝@penkzhouポインティングのこと)
開始からAndroid4.4 AsyncTask
とは異なった動記述 更新:2 ます。あり は固定 防止 AsyncTask
作成からも多くのスレッド)。
前のAndroid4.4(API19) AsyncTask
下記の分野:
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);
Android4.4(API19)上記の項目を変更す:
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);
この変化が大きのサイズのキュー128項目を減らの最大数のスレッドのCPUのコア数*2+1.アプリではまだ提出しと同じ数の事ができます。
他のヒント
これにより、API 4+(Android 1.6+)を使用したすべてのAndroidバージョンで並列実行が可能になります。
@TargetApi(Build.VERSION_CODES.HONEYCOMB) // API 11
void startMyTask(AsyncTask asyncTask) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
else
asyncTask.execute(params);
}
これは、Arhimedの優れた答えの要約です。
Project Build TargetsとしてAPIレベル11以降を使用してください。 Eclipseで、つまり Project > Properties > Android > Project Build Target
. この意志 いいえ 逆方向の互換性を破り、APIレベルを低下させます。 心配しないでください、あなたが誤って紹介された機能を後で紹介する場合、あなたは糸くずのエラーが得られます minSdkVersion
. 。あなたが本当に以降に紹介された機能を本当に使用したい場合 minSdkVersion
, 、注釈を使用してこれらのエラーを抑制することができますが、その場合、互換性に注意する必要があります あなた自身. 。これはまさに上記のコードスニペットで起こったことです。
@sulaiの提案をより一般的にする:
@TargetApi(Build.VERSION_CODES.HONEYCOMB) // API 11
public static <T> void executeAsyncTask(AsyncTask<T, ?, ?> asyncTask, T... params) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
else
asyncTask.execute(params);
}
@sulaiの非常に良い要約に@arhimedの真っ白な答えに最新の更新(更新4)を含めるだけです。
void doTheTask(AsyncTask task) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Android 4.4 (API 19) and above
// Parallel AsyncTasks are possible, with the thread-pool size dependent on device
// hardware
task.execute(params);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // Android 3.0 to
// Android 4.3
// Parallel AsyncTasks are not possible unless using executeOnExecutor
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
} else { // Below Android 3.0
// Parallel AsyncTasks are possible, with fixed thread-pool size
task.execute(params);
}
}
Android開発者のロードの例ビットマップの例は、カスタムAsynctask(Jellybeanからコピー)を効率的に使用するため、11未満のAPIでexecuteOnexecutorを使用できます。
http://developer.android.com/training/displaying-bitmaps/index.html
コードをダウンロードして、utilパッケージに移動します。
それは可能です。私のAndroidデバイスバージョンは4.0.4で、android.os.s.build.version.sdk_intは15です
私には3つのスピナーがいます
Spinner c_fruit=(Spinner) findViewById(R.id.fruits);
Spinner c_vegetable=(Spinner) findViewById(R.id.vegetables);
Spinner c_beverage=(Spinner) findViewById(R.id.beverages);
また、私は非同期のクラスを持っています。
これが私のスピナー読み込みコードです
RequestSend reqs_fruit = new RequestSend(this);
reqs_fruit.where="Get_fruit_List";
reqs_fruit.title="Loading fruit";
reqs_fruit.execute();
RequestSend reqs_vegetable = new RequestSend(this);
reqs_vegetable.where="Get_vegetable_List";
reqs_vegetable.title="Loading vegetable";
reqs_vegetable.execute();
RequestSend reqs_beverage = new RequestSend(this);
reqs_beverage.where="Get_beverage_List";
reqs_beverage.title="Loading beverage";
reqs_beverage.execute();
これは完全に機能しています。私のスピナーは1つずつロードしました。ユーザーExecuteOnexecutorはありませんでした。
これが私のasync-taskクラスです
public class RequestSend extends AsyncTask<String, String, String > {
private ProgressDialog dialog = null;
public Spinner spin;
public String where;
public String title;
Context con;
Activity activity;
String[] items;
public RequestSend(Context activityContext) {
con = activityContext;
dialog = new ProgressDialog(activityContext);
this.activity = activityContext;
}
@Override
protected void onPostExecute(String result) {
try {
ArrayAdapter<String> adapter = new ArrayAdapter<String> (activity, android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(adapter);
} catch (NullPointerException e) {
Toast.makeText(activity, "Can not load list. Check your connection", Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (Exception e) {
Toast.makeText(activity, "Can not load list. Check your connection", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
super.onPostExecute(result);
if (dialog != null)
dialog.dismiss();
}
protected void onPreExecute() {
super.onPreExecute();
dialog.setTitle(title);
dialog.setMessage("Wait...");
dialog.setCancelable(false);
dialog.show();
}
@Override
protected String doInBackground(String... Strings) {
try {
Send_Request();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void Send_Request() throws JSONException {
try {
String DataSendingTo = "http://www.example.com/AppRequest/" + where;
//HttpClient
HttpClient httpClient = new DefaultHttpClient();
//Post header
HttpPost httpPost = new HttpPost(DataSendingTo);
//Adding data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("authorized","001"));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// execute HTTP post request
HttpResponse response = httpClient.execute(httpPost);
BufferedReader reader;
try {
reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line) ;
}
JSONTokener tokener = new JSONTokener(builder.toString());
JSONArray finalResult = new JSONArray(tokener);
items = new String[finalResult.length()];
// looping through All details and store in public String array
for(int i = 0; i < finalResult.length(); i++) {
JSONObject c = finalResult.getJSONObject(i);
items[i]=c.getString("data_name");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
タスクを並行して実行する場合は、メソッドを呼び出す必要があります executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "your task name")
3.0のAndroidバージョンの後;ただし、この方法はAndroid 3.0以前と1.6以降に存在していません。なぜなら、それ自体が並行して実行するため、プロジェクトで独自のAsynctaskクラスをカスタマイズすることをお勧めします。