如何在Android中管理Runnable任务的队列 [英] How to Manage Queue of Runnable Tasks in Android

查看:202
本文介绍了如何在Android中管理Runnable任务的队列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个任务/ Runnable(即从互联网下载图像),这是随着用户滚动Android应用程序列表而生成的任务。

I have multiple tasks/Runnable (i.e. downloading images from internet), which are generated as the user scrolls through a list in a Android App.

我无法控制一次生成多少个任务/ Runnable,这可能在100.但是我只想并行执行n(10)个任务。所以,我打算建立一个设计,一旦生成一个新的task / runnable,它将被添加到一个队列( List< Runnable> )中,并通过 Executors.newFixedThreadPool(10),我将并行执行前10个可运行的任务。现在,一旦任务/ Runnable完成,我应该能够从队列( List< Runnable> )中删除它们,并且应该能够执行新任务/ Runnable在FIFO中排队。

I cannot control how many tasks/Runnable are generated at a time, this could in 100. But I want to execute only n(10) tasks in parallel. So, I am planning to build a design, where as soon as a new task/runnable is generated, it will be added to a queue (List<Runnable>) and through Executors.newFixedThreadPool(10), I will execute only first 10 runnable tasks in parallel. Now as soon as the tasks/Runnable are completed, I should be able to remove them from queue (List<Runnable>) and should be able to execute new tasks/Runnable which are in queue, in FIFO.

我有两个类用于此设计。首先是 ExecutorManager 它是一个单例类,并管理10个并行任务的执行,其次是实现的$ code> ImageDownloader runnable 并负责下载图像。我不知道什么是通知 ExecutorManager 完成任务/下载的最佳方法,它可以从队列中执行新任务。我正在跟踪FIFO,所以我将始终从队列中的前10个任务开始执行,但是如何知道哪个任务已经完成,哪个任务要从队列中删除?

I have two classes for this design. First is ExecutorManager which is a singleton class and manages the executions of 10 parallels tasks and second is the ImageDownloader class which implements runnable and is responsible to download the image. I am not sure what is the best way to inform the ExecutorManager that the task/download is completed and it can execute new task from the queue. I am following FIFO, so I will always start execution from first 10 tasks in the queue, but how will I get to know, which task is completed and which one to remove from the Queue?

public class ImageDownloader implements Runnable{

    DownloadListener mDownloadListener;

    public ImageDownloader(DownloadListener mDownloadListener, String URL){
        this.mDownloadListener = mDownloadListener;
    }


    @Override
    public void run() {
        //Download the Image from Internet
            //ToDo
        //if Success in download
            mDownloadListener.onDownloadComplete();
        //if Error in download
            mDownloadListener.onDownloadFailure();
        //Inform the Executor Manager that the task is complete and it can start new task
         incrementCount();
    }

    private static synchronized void incrementCount(){
        ExecutorManager.getInstance().OnTaskCompleted();// is there a better way to do it
    }
}



public class ExecutorManager {

    private static ExecutorManager Instance;
    ExecutorService executor = Executors.newFixedThreadPool(Constants.NumberOfParallelThread);
    ArrayList<Runnable> ExecutorQueue = new ArrayList<Runnable>();
    int ActiveNumberOfThread = 0;

    private ExecutorManager(){
    }

    public static ExecutorManager getInstance(){

        if(Instance==null){
            Instance = new ExecutorManager();

        }
        return Instance;
    }

    private void executeTask(){
        if(ExecutorQueue.size()>0 && ActiveNumberOfThread < Constants.NumberOfParallelThread){
            ++ActiveNumberOfThread;
            executor.execute(ExecutorQueue.get(0));//Execute the First Task in Queue
        }
    }

    public void enQueueTask(Runnable Task){

        ExecutorQueue.add(Task);
        executeTask();
    }

    public void removeFromQueue(){
        //How to know, which task to remove?
        ExecutorQueue.remove(0);
    }

    public void OnTaskCompleted(){
        --ActiveNumberOfThread;
        removeFromQueue();
        executeTask();
    }

}


推荐答案

嗯,你好运。你不需要告诉执行官任何东西。一个 ExecutorService BlockingQueue 为您处理队列。所有你需要做的是将 Runnable 提交给ExecutorService。它会坚持下去。如果有任何开放的线程,它将立即运行。否则,它将等待其他 Runnables 之一完成执行。一旦完成,将需要下一个。

Well, you're in luck. You don't have to tell the ExecutorManager anything at all. An ExecutorService with a BlockingQueue handles queues for you. All you have to do is submit the Runnable to the ExecutorService. It will hold on to it. If there are any open threads, it will run it instantly. Else, it will wait until one of the other Runnables finishes execution. Once it finishes, it will take the next one.

如果您查看执行器#newFixedThreadPool 实际上只需创建一个 ThreadPoolExecutor nThreads 线程支持一个 LinkedBlockingQueue 像这样:

If you look at the source code for Executors#newFixedThreadPool, it actually just creates a ThreadPoolExecutor with nThreads threads backed by a LinkedBlockingQueue like so:

public static ExecutorService newFixedThreadPool(int nThreads) {
         return new ThreadPoolExecutor(nThreads, nThreads,
                                       0L, TimeUnit.MILLISECONDS,
                                       new LinkedBlockingQueue<Runnable>());
} 

这篇关于如何在Android中管理Runnable任务的队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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