0

私は自分のアプリケーションで多くのAsyncTaskクラスを使用しています。私はいつもそれらを使用して起動します:Android - ThreadPoolExecutorがキュー制限に達したかどうかを確認する方法

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    asyncTask.execute(); 
} 

最近RejectedExecutionException例外が発生しました。私はこれについて読んで、なぜこれが起こるか(スレッドプールエグゼキュータがそのキューに持つことができるタスクの最大数を超えている)を理解する。

しかし、私はこれを避けるために、スレッドプールエグゼキュータに空きスロットがあるかどうかを確認する方法についてはどこにも読んでいませんでした。私がasyncTask.execute()をテストしたものから;メソッドにはこの制限がありません。

だから私はこのような何かを探しています:API 9までの後方互換性でこれを実装する方法の

if(executorCanHandlerAnotherQueue()){ 
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
     asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
    } else { 
     asyncTask.execute(); 
    } 
} 
else{ 
    asyncTask.execute(); 
} 

任意のアイデア?

答えて

0

AsyncTaskはスレッドプールパターンを使用するため、スレッドのデフォルト数だけを提供します。 execute()を呼び出すと、タスクはワーカースレッドが自由に行うのを待機します。

実並列で実行するには、executeOnExecutor()を呼び出すことができます。しかし、これも限られています(最大タスク数=スレッドプールサイズ+タスクキューサイズ)。あなたはこのようなスレッドやタスクキューの数増加するカスタムエグゼキュータを作成することができます

:アンドロイド用ハニカムより低いキュータ()関数を実行するために

public static final Executor CUSTOM_THREAD_POOL_EXECUTOR 
     = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, 
       TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); 

を、あなたは

AsyncTaskCompat.executeParallel(task, params); 

を使用することができますサポートv4ライブラリから。

あなたはこのanswer

UPDATE、より詳細な情報を確認することができます、実行前に、使用可能なエグゼキュータをチェックするための

あなたがそのような小さな関数記述することができます。

boolean canExecutorAddAnotherQueue(ThreadPoolExecutor executor){ 
     int active = executor.getActiveCount(); 
     int corePoolSize = executor.getCorePoolSize(); 
     int poolSize = executor.getPoolSize(); 
     if (active < corePoolSize || active < poolSize) return true; 
     int queueSize = executor.getQueue().size(); 
     if (queueSize < MAX_QUEUE_SIZE_YOU_DEFINED) return true; 
     return false; 
    } 

をしかし、それはおそらくいくつかを欠場ケースも受け入れました。

FINAL ANSWER:あなたがあなた自身のハンドラを記述することができ

public ThreadPoolExecutor(int corePoolSize, 
          int maximumPoolSize, 
          long keepAliveTime, 
          TimeUnit unit, 
          BlockingQueue<Runnable> workQueue, 
          ThreadFactory threadFactory, 
          RejectedExecutionHandler handler) 

 try { 
      //execute asynctask 
     } catch (RejectedExecutionException e){ 
      //Handle when has exception thrown 
     } 

またはカスタムハンドラを使用して:

だから私は、最良の選択はトライキャッチを使用していましたタスクが拒否されたケースを処理し、RejectedExecutionExceptionをもうスローしないでください。

+0

あなたのレスポンスに感謝しますが、それは問題ではありませんでした。私はすでにこれを知っています。私が探しているのは、 'boolean canExecutorAddAnotherQueue()'のようなメソッドのタイプで、Executorスレッドプールに自分のasyncTaskを追加できるかどうかを判断するために使用します。 – Anonymous

+0

私の更新された答えを見てください。あなたのケースのカスタムハンドラ。 – Ken

+0

あなたが書いた方法はもっとよく似ています。キャッチしようとすると貧弱なアプローチ...しかし、私はカスタムThreadPoolExecutorを使用しません。 AsyncTaskはそれ自身のものを使用します。したがって、MAX_QUEUE_SIZE_YOU_DEFINEDは、AsyncTaskが定義するMAX_QUEUE_SIZE_YOU_DEFINEDです。どちらが私が理解しているから、デバイスのコアの数に依存します。デバイス上でテストすると、getQueueSize()が128の場合に例外がスローされることがわかりましたが、APIを使用してその番号を取得する方法はわかりません。 – Anonymous

関連する問題