Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Executor上的AsyncTask和PriorityBlockingQueue实现问题_Android_Multithreading_Android Asynctask_Priority Queue - Fatal编程技术网

Android Executor上的AsyncTask和PriorityBlockingQueue实现问题

Android Executor上的AsyncTask和PriorityBlockingQueue实现问题,android,multithreading,android-asynctask,priority-queue,Android,Multithreading,Android Asynctask,Priority Queue,在的浪潮中,我尝试实现一个AsyncTask变体,其中包含可以优先排序的任务 在我的CustomAsyncTask课程中,我有: public abstract class CustomAsyncTask<Params, Progress, Result> { private static int CORE_POOL_SIZE = 1; private static int MAXIMUM_POOL_SIZE = 1; private static fin

在的浪潮中,我尝试实现一个
AsyncTask
变体,其中包含可以优先排序的任务

在我的
CustomAsyncTask
课程中,我有:

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);

   //...
}
这是可行的:如果池大小为1,下载将逐个执行;如果池大小为2,等等

注意:优先级整数具有任意值:

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不能强制转换为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输出。但它给出了一个想法。当两个以上的任务排队时,应用程序FCs


CustomAsyncTask
,与
AsyncTask
一样,使用
静态
队列。目前,该队列上的所有内容都将通过您的
下载任务比较程序运行。但是,
downloadstaskscomparator
仅适用于
downloadstask
。只要您只使用
DownloadTask
,而不使用
CustomAsyncTask
的其他子类,就可以了。但是,显然您还有一些其他匿名内部类扩展了
CustomAsyncTask
,而这不是
DownloadTask


使用
getPriority()
方法作为
abstract
方法,使
CustomAsyncTask
成为
abstract
。将
DownloadTaskComparator
重命名为
CustomAsyncTaskComparator
,并让它比较
CustomAsyncTask
实例。然后,
CustomAsyncTask
的其他子类需要实现它们自己的
getPriority()
方法,以使它们能够与工作队列中的
DownloadTask
实例一起排序。

CustomAsyncTask
AsyncTask
一样,使用
静态
队列。目前,该队列上的所有内容都将通过您的
下载任务比较程序运行。但是,
downloadstaskscomparator
仅适用于
downloadstask
。只要您只使用
DownloadTask
,而不使用
CustomAsyncTask
的其他子类,就可以了。但是,显然您还有一些其他匿名内部类扩展了
CustomAsyncTask
,而这不是
DownloadTask


使用
getPriority()
方法作为
abstract
方法,使
CustomAsyncTask
成为
abstract
。将
DownloadTaskComparator
重命名为
CustomAsyncTaskComparator
,并让它比较
CustomAsyncTask
实例。然后,
CustomAsyncTask
的其他子类需要实现它们自己的
getPriority()
方法,以使它们能够与工作队列中的
DownloadTask
实例一起排序。

CustomAsyncTask
AsyncTask
一样,使用
静态
队列。目前,该队列上的所有内容都将通过您的
下载任务比较程序运行。但是,
downloadstaskscomparator
仅适用于
downloadstask
。只要您只使用
DownloadTask
,而不使用
CustomAsyncTask
的其他子类,就可以了。但是,显然您还有一些其他匿名内部类扩展了
CustomAsyncTask
,而这不是
DownloadTask


使用
getPriority()
方法作为
abstract
方法,使
CustomAsyncTask
成为
abstract
。将
DownloadTaskComparator
重命名为
CustomAsyncTaskComparator
,并让它比较
CustomAsyncTask
实例。然后,
CustomAsyncTask
的其他子类需要实现它们自己的
getPriority()
方法,以使它们能够与工作队列中的
DownloadTask
实例一起排序。

CustomAsyncTask
AsyncTask
一样,使用
静态
队列。目前,该队列上的所有内容都将通过您的
下载任务比较程序运行。但是,
downloadstaskscomparator
仅适用于
downloadstask
。只要您只使用
DownloadTask
,而不使用
CustomAsyncTask
的其他子类,就可以了。但是,显然您还有一些其他匿名内部类扩展了
CustomAsyncTask
,而这不是
DownloadTask


使用
getPriority()
方法作为
abstract
方法,使
CustomAsyncTask
成为
abstract
。将
DownloadTaskComparator
重命名为
CustomAsyncTaskComparator
,并让它比较
CustomAsyncTask
实例。然后,
CustomAsyncTask
的其他子类需要实现它们自己的
getPriority()
方法,以使它们能够与工作队列中的
DownloadTask
实例一起排序。

正如您在查看
AsyncTask
实现时可能注意到的那样,它在内部使用一个
FutureTask
来处理后台任务,这就是交给
Executor
并可能在其工作队列中排队的任务。由于您已经在派生自己的实现,因此可以将
FutureTask
替换为一个自定义派生,该派生包含对
AsyncTask
的引用,可从
比较器访问
DownloadTask dt = new DownloadTask(..., PRIORITY_HIGH, ...);
dt.executeOnExecutor(CustomAsyncTask.PRIORITY_THREAD_POOL_EXECUTOR);
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)
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
        Params... params) {
    if (mStatus != Status.PENDING) {
        switch (mStatus) {
            case RUNNING:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task is already running.");
            case FINISHED:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task has already been executed "
                        + "(a task can be executed only once)");
        }
    }

    mStatus = Status.RUNNING;

    onPreExecute();

    mWorker.mParams = params;
    exec.execute(mFuture);

    return this;
}
/* Executor used by AsyncTask. Use it with executeOnExecutor()*/
class PriorityExecutor extends ThreadPoolExecutor{

    //workQueue is a instance of PriorityBlockingQueue<Runnable>
    public PriorityExecutor(int corePoolSize, int maximumPoolSize,
            long keepAliveTime, TimeUnit unit,
            BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory);

    }

    //wrap the runnable passed in.
    @Override
    public void execute(Runnable command) {
        super.execute(new PriorityRunnableWrapper(command));
    }
}

//a wrapper class
class PriorityRunnableWrapper implements Runnable ,Comparable<PriorityRunnableWrapper>{

    long addedTime;//the "priority"
    Runnable r;

    public PriorityRunnableWrapper(Runnable r){
        this.r = r;
        addedTime = System.nanoTime();//in my case the timestamp is the priority
    }

    @Override
    public void run() {
        r.run();
    }

    @Override
    public int compareTo(PriorityRunnableWrapper another) {
        if(addedTime == another.addedTime)return 0;
        return addedTime - another.addedTime > 0 ? -1 : 1;
    }

}