Executor 上的 AsyncTask 和 PriorityBlockingQueue 实现问题 [英] AsyncTask on Executor and PriorityBlockingQueue implementation issue
问题描述
关于这个SO问题的浪潮以及来自另一个,我正在尝试使用任务实现 AsyncTask
变体可以优先考虑.
On the wave of this SO question and with many hints from another one, I'm trying to implement an AsyncTask
variant with tasks that can be prioritized.
在我的 CustomAsyncTask
类中,我有:
In my CustomAsyncTask
class I have:
public abstract class CustomAsyncTask<Params, Progress, Result> {
private static int CORE_POOL_SIZE = 1;
private static int MAXIMUM_POOL_SIZE = 1;
private static final int KEEP_ALIVE = 1;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "CustomAsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<DownloadTask> pPoolWorkQueue =
new PriorityBlockingQueue<DownloadTask>(10, new DownloadTasksComparator());
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Executor PRIORITY_THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, (PriorityBlockingQueue) pPoolWorkQueue, sThreadFactory);
//...
}
比较器:
public class DownloadTasksComparator implements Comparator<DownloadTask> {
@Override
public int compare(DownloadTask arg0, DownloadTask arg1) {
int res;
if (arg0 == null && arg1 == null) {
res = 0;
} else if (arg0 == null) {
res = -1;
} else if (arg1 == null) {
res = 1;
}
res = arg0.getPriority() - arg1.getPriority();
return res;
}
}
在扩展 CustomAsyncTask
的 DownloadTask
类中,我有一个 priority
Integer 字段和一个 getPriority()
方法.
In the DownloadTask
class extending CustomAsyncTask
I have a priority
Integer field and a getPriority()
method.
我将任务执行称为:
DownloadTask dt = new DownloadTask(..., PRIORITY_NORMAL, ...);
dt.executeOnExecutor(CustomAsyncTask.PRIORITY_THREAD_POOL_EXECUTOR);
这是有效的:如果池大小为 1,则下载将一一执行;如果池大小为 2,依此类推
This works: if the pool sizes are 1, the downloads get executed one by one; if pool size is 2, etc.
注意:优先级整数具有任意值:
note: priority Integers have arbitrary values:
public static final int PRIORITY_HIGH = 10;
public static final int PRIORITY_NORMAL = 1;
但如果我将任务称为:
DownloadTask dt = new DownloadTask(..., PRIORITY_HIGH, ...);
dt.executeOnExecutor(CustomAsyncTask.PRIORITY_THREAD_POOL_EXECUTOR);
我有一个 java.lang.ClassCastException: my.pkg.name.CustomAsyncTask$3 cannot be cast to my.pkg.name.DownloadTask
然后
at my.pkg.name.DownloadTasksComparator.compare(DownloadTasksComparator.java:1)
at java.util.concurrent.PriorityBlockingQueue.siftUpUsingComparator(PriorityBlockingQueue.java:334)
at java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:447)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1295)
at my.pkg.name.CustomAsyncTask.executeOnExecutor(CustomAsyncTask.java:494)
at my.pkg.name.GetDownloadTaskListener$1.finishDownload(GetDownloadTaskListener.java:180)
at my.pkg.name.DownloadTask.onPostExecute(DownloadTask.java:330)
at my.pkg.name.DownloadTask.onPostExecute(DownloadTask.java:1)
at my.pkg.name.CustomAsyncTask.finish(CustomAsyncTask.java:536)
at my.pkg.name.CustomAsyncTask.access$0(CustomAsyncTask.java:532)
at my.pkg.name.CustomAsyncTask$InternalHandler.handleMessage(CustomAsyncTask.java:549)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
全部来自 AndroidRuntime
我真的不知道...
编辑:在这一点上,我已经封装了一个小型 Eclipse 项目,它以与更大的应用程序完全相同的方式实现事物并遇到同样的问题.它逐字地借用了 CustomAsyncTaskComparator
和 CustomAsyncTask
.没有给出视觉反馈.应用程序的进度只是一些 LogCat 输出.但它给出了想法.当两个以上的任务排队时,应用程序 FC.
EDIT: At this point, I've wrapped a small Eclipse project that implements things exactly the same way of the bigger application and suffers from the same issue. It borrows CustomAsyncTaskComparator
and CustomAsyncTask
verbatim. No visual feedback is given. The app's progress is just some LogCat output. But it gives the idea. When more than two tasks are enqueued, the app FCs.
https://www.dropbox.com/s/lrg4kscgw3f1xwr/ConcurrentTest.tar.gz
推荐答案
正如您在查看 AsyncTask
实现时可能已经注意到的那样,它在内部使用 FutureTask
来处理后台任务,这就是交给 Executor
并可能在它的工作队列中排队的东西.由于您已经在派生自己的实现,您可以将 FutureTask
替换为自定义派生对象,该派生对象包含对 AsyncTask
的引用,可从您的 Comparator
实现.
As you may have noticed while looking through the AsyncTask
implementation, it internally uses a FutureTask
to handle the background task, and that is what gets handed on to the Executor
and potentially queued on it's work queue. Since you are already deriving your own implementation, you could replace the FutureTask
with a custom derivative that holds a reference to the AsyncTask
, to be accessed from your Comparator
implementation.
此外,不要替换自定义 AsyncTask
派生类的默认静态 Executor
,而是应该在您的子类,以便它可以以通用方式使用.
Also, instead of replacing the default static Executor
of your custom AsyncTask
derivative, you should instead use the executeOnExecutor()
method in your subclasses so that it can be used in a generic manner.
这篇关于Executor 上的 AsyncTask 和 PriorityBlockingQueue 实现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!