2017-03-24 5 views
1

私はこの問題を持っている: 私はJsoup.connect(url).get()を使用して複数のURLからアンドロイドasynctaskにいくつかのデータを取得し、その後の活動でそれを示しています。問題は、スレッドを中断してプロセッサを解放してからjsoup結果を取得するかタイムアウト例外をキャッチする必要があることがあることです。タイムアウトの前にJsoup getスレッドを中断するにはどうしたらいいですか?

コードコードの重要な部分は、次のようになります。

@Override 
    protected Void doInBackground(String... urls) { 
      int cpuCount = Runtime.getRuntime().availableProcessors(); 

      BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(); 
      ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        cpuCount, 
        cpuCount, 
        30, 
        TimeUnit.SECONDS, 
        queue); 

      final CountDownLatch countDownLatch = new CountDownLatch(urls.length); 

      for (final String url : urls) { 
       threadPoolExecutor.execute(new Runnable() { 
        @Override 
        public void run() { 
         String html = null; 
         try { 
          html = Jsoup.connect(url).get().outerHtml(); 
         } catch (Exception ignored) { 
         } 

         if (html != null) { 
          publishProgress(videoStream); 
         } 
         countDownLatch.countDown(); 
        } 
       }); 
      } 
     countDownLatch.await(); 
     return null; 
    } 

    @Override 
    protected void onProgressUpdate(String... result) { 
     updateUiStuff(result[0]); 
    } 

私はスレッドプールエグゼキュータを使用していた理由は、1つのつではなく、結果を待つので、それは並列で複数のスレッドでの接続を行うことで、第2の接続を開くなどである。

私はonPreExecuteで設定されたボタン、上cancel(true); OR threadPoolExecutor.shutDown();threadPoolExecutor.shutDownNow();をやってみましたが、それはRunnable秒を停止していません。私が活動を終了しても、Runnableはタイムアウトするまで実行を続け、それまではjsoup接続が実行されているのでネットワーク上で何もできません。正しい方向に私を指差してください。多くのおかげで、これは本当に愚かな質問である場合私は謝罪しますが、私はここで同様のものを見つけることができませんでした。

要するに、AsyncTaskがキャンセルされたときにスレッドを停止する必要があります。

答えて

0

ThreadPoolExecutorは、設定するには、いくつかの経験を必要とする汎用のエグゼキュータです。これは、クラスの他のファクトリメソッドによって返されたエグゼキュータによって、ではなく、が満たされていない経験豊富なプログラマのためのゲートウェイです。このクラスのコンストラクタの一つのJavadocにも書類それ:

{@link Executors}工場 方法の代わりに、この汎用コンストラクタのいずれかを使用する方が便利かもしれません。

あなたはまだThreadPoolExectorを使用したいと思っていますか? ExecutorsThreadFactoryのメソッドには、非同期タスクを実行する実際のスレッドを作成するメソッドを常に用意することができます。 ThreadPoolExecutorに行く必要はありません。

上記の呼び出しでは、すべてのスレッドを30秒(keepAliveTime)待つようにして、終了前に無駄に待機させます。あなたはそれをしてもよろしいですか?

また、タスクとしてRunnableインスタンスのみを使用します。代わりにCallableインスタンスを使用すると考えていた場合は、Futureを返すsubmitメソッドを使用してキャンセルできます。これにより、invokeAll()メソッドの使用が容易になり、Callableのコレクションを渡し、返されたFutureを照会または取り消すことができます。あなたはcancel(true)でしたが、上記の方法はFutureでのみ利用可能です。

エグゼキュータやサービスをシャットダウンする信頼性の高い方法は次のとおりです。

  • shutdown()メソッドを使用して通常のシャットダウンを試みるためにそれをシャットダウンします。
  • 終了を待ちます。
  • shutdownNow()メソッドを使用して、必要な場合のみ、にシャットダウンしてください。返された場合は、Runnableの返されたリストを適切に処理してください。
  • 例外を適切に処理します(これは強調する必要があります)。私はJsoup.connectがさまざまな例外をスローすることを確信していますし、それらを正しく処理する必要があります。あなたの場合、悲しいことに、例外変数の名前をignoredにすることさえできます!インターネットで読んだことすべてを信じてはいけません。

あなたはExecutorServiceと、このようにいくつかの経験を得た後、あなたはFuture完全な非同期タスクなどを提供するCompletionServiceに進むことができます。これは、特にタスクが可変IOバインドアクティビティで構成されている場合には、並列処理をより有効に活用します。

関連する問題