如何在超时之前中断Jsoup get线程?

时间:2017-03-24 18:17:50

标签: java android multithreading android-asynctask jsoup

我有这个问题: 我使用Jsoup.connect(url).get()从多个网址获取android asynctask中的一些数据,然后在Activity中显示它。问题是有时我需要在获取jsoup结果或捕获超时异常之前中断线程并释放处理器。

代码的重要部分如下所示:

    @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]);
    }

我使用线程池执行程序的原因是它并行处理多个线程中的连接,而不是等待一个结果并打开第二个连接,依此类推。

我尝试在按钮上执行cancel(true);threadPoolExecutor.shutDown();threadPoolExecutor.shutDownNow();,该按钮在onPreExecute中设置但它没有停止Runnable。即使我关闭活动,Runnable也会继续运行,直到它们超时,直到那时我无法在网络上执行任何操作,因为jsoup连接仍在运行。请指出我正确的方向。非常感谢,如果这是一个非常愚蠢的问题我很抱歉,但我在这里找不到类似的问题。

简而言之:我需要在AsyncTask取消时停止线程。

1 个答案:

答案 0 :(得分:0)

ThreadPoolExecutor是一个通用的执行程序,需要一些配置经验。它是那些经验丰富的程序员的网关,这些程序员的需求在Executors类中由其他工厂方法返回的执行者满足(经过充分测试)之后 。这个类的构造函数之一的Javadoc甚至记录了它:

  

使用{@link Executors}工厂之一可能更方便     方法而不是这个通用构造函数。

您是否确信仍想使用ThreadPoolExector?请注意,您始终可以为Executors ThreadFactory提供创建运行异步任务的实际线程的方法。您不必转到ThreadPoolExecutor

在上面的调用中,您使每个线程等待30秒( keepAliveTime ),这使得它在终止前等待。你确定要的吗?

您还只使用Runnable个实例作为您的任务。如果您考虑使用Callable实例,则可以使用submit方法返回可以取消的Future。这也有助于使用invokeAll()方法,该方法允许您传入Callable的集合并查询/取消返回的Future。您在上面说过cancel(true),但请注意,该方法仅适用于Future

关闭执行程序或执行程序服务的可靠方法是:

  • 关闭它以尝试使用shutdown()方法有序关闭。
  • 等待终止。
  • 仅在需要时,使用shutdownNow()方法立即关闭 ,如果确实如此,请正确处理返回的Runnable列表。
  • 处理异常(需要强调)。我确信Jsoup.connect会抛出各种不同的异常,你应该正确处理它们。在您的情况下,遗憾的是,您甚至将异常变量命名为ignored!请不要相信您在互联网上阅读的所有内容;)。

通过这种方式获得ExecutorService的一些使用经验之后,您可以转到CompletionService,其中提供Future 作为异步任务完成。这会更好地利用并行性,尤其是当任务由可变的IO绑定活动组成时。