我有这个问题:
我使用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取消时停止线程。
答案 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绑定活动组成时。