私の Android アプリは、産業のコンテキストでのデータ収集用です。フルタイムの従業員はアプリを使用して多くの観察結果 (写真、ジオタグ、テキストなど) を取得し、Wi-Fi が利用可能になったときにまとめてアップロードします。
Amazon の Android SDK を使用して S3 の一括アップロードを実行しています。内部では、このライブラリはアップロードごとにスレッドプール スレッドを使用しており、ときどき RejectedExecutionException が発生します。これをより回復力のある方法で処理できるかどうか興味があります...
私のコードは並列アップロードを実行しないことに注意してください。写真ごとに s3.transfer.TransferManager.upload() を順番に呼び出し、完了を待ってから続行する単一のスレッドを使用します。したがって、いつでも、関連するスレッドは最大 2 つしか存在しないはずです。1 つは私のコード用で、もう 1 つは Amazon からディスパッチされたスレッド用です。
しかし、スレッド プールに空きがない場合、ユーザーが RejectedExecutionException に遭遇することがあります。
java.util.concurrent.RejectedExecutionException: pool=0/10, queue=0
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1961)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:794)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1315)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:107)
at com.amazonaws.services.s3.transfer.internal.UploadMonitor.<init>(Unknown Source)
at com.amazonaws.services.s3.transfer.TransferManager.upload(Unknown Source)
at com.amazonaws.services.s3.transfer.TransferManager.upload(Unknown Source)
at com.amazonaws.services.s3.transfer.TransferManager.upload(Unknown Source)
クラッシュ レポートに含まれる他のすべてのスレッド スタックに目を通すと、おそらく他の AsyncTasks は単に過去のアップロードであり、まだクリーンアップする機会がないのではないでしょうか? たとえば、私はこれらの多くを見ます:
java.lang.Object.wait(Native Method)
java.lang.Thread.parkFor(Thread.java:1424)
java.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)
sun.misc.Unsafe.park(Unsafe.java:337)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2016)
java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:411)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1021)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
java.lang.Thread.run(Thread.java:1019)
これらのスレッドをクリーンアップする機会が必要なだけという可能性はありますか? もしそうなら、一括アップロードを続行できるように、予測可能な時間/リスクでこれを達成するための比較的簡単なメカニズムはありますか?
メイン アップロード スレッドの thread.sleep(0) に相当する (概念的な) ものは、プールをクリーンアップする機会を与えてから、アップロードを再試行できるのでしょうか?
どんな考えや経験でも大歓迎です。私はこれを社内で再現することができず、予測できないため、ここで実験する能力は限られています...
ありがとう。