Executor 上的 AsyncTask 和 PriorityBlockingQueue 实现问题 [英] AsyncTask on Executor and PriorityBlockingQueue implementation issue

查看:21
本文介绍了Executor 上的 AsyncTask 和 PriorityBlockingQueue 实现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于这个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;
    }
}

在扩展 CustomAsyncTaskDownloadTask 类中,我有一个 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 项目,它以与更大的应用程序完全相同的方式实现事物并遇到同样的问题.它逐字地借用了 CustomAsyncTaskComparatorCustomAsyncTask.没有给出视觉反馈.应用程序的进度只是一些 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆