【问题标题】:How to Manage Queue of Runnable Tasks in Android如何在 Android 中管理可运行任务队列
【发布时间】:2016-08-17 13:35:54
【问题描述】:

我有多个任务/可运行(即从互联网下载图像),这些是在用户滚动浏览 Android 应用程序中的列表时生成的。

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

我有两个用于此设计的课程。第一个是ExecutorManager,它是一个单例类,管理10 个并行任务的执行,第二个是ImageDownloader 类,它实现了runnable,负责下载图像。我不确定通知ExecutorManager 任务/下载已完成并且它可以从队列中执行新任务的最佳方式是什么。我遵循先进先出,所以我总是从队列中的前 10 个任务开始执行,但是我如何知道哪个任务已完成以及从队列中删除哪个任务?

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

}

【问题讨论】:

    标签: java android multithreading design-patterns


    【解决方案1】:

    嗯,你很幸运。您根本不必告诉 ExecutorManager 任何事情。带有BlockingQueueExecutorService 为您处理队列。您所要做的就是将Runnable 提交给ExecutorService。它会坚持下去。如果有任何打开的线程,它将立即运行它。否则,它将等到另一个Runnables 之一完成执行。完成后,将进行下一个。

    如果您查看Executors#newFixedThreadPool 的源代码,它实际上只是创建了一个ThreadPoolExecutor,其中nThreads 线程由LinkedBlockingQueue 支持,如下所示:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多