Java 如何在Android中管理可运行任务的队列

Java 如何在Android中管理可运行任务的队列,java,android,multithreading,design-patterns,Java,Android,Multithreading,Design Patterns,我有多个任务/可运行(即从互联网下载图像),这些任务是用户在Android应用程序中滚动列表时生成的 我无法控制一次生成多少任务/可运行任务,这可能需要100个。但是我只想并行执行n(10)个任务。因此,我计划构建一个设计,一旦生成一个新任务/可运行任务,它将被添加到队列(列表)中,并通过执行器。newFixedThreadPool(10),我将只并行执行前10个可运行任务。现在,一旦任务/Runnable完成,我应该能够将它们从队列(列表)中删除,并且应该能够以FIFO方式执行队列中的新任务/

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

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

这个设计我有两门课。第一个是
executomanager
,它是一个单例类,管理10个并行任务的执行;第二个是
ImageDownloader
类,它实现
runnable
,并负责下载映像。我不确定通知
executomanager
任务/下载已完成并且可以从队列中执行新任务的最佳方式。我遵循FIFO,所以我总是从队列中的前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();
    }

}
公共类ImageDownloader实现可运行{
DownloadListener mDownloadListener;
公共图像下载程序(DownloadListener mDownloadListener,字符串URL){
this.mdownloadstener=mdownloadstener;
}
@凌驾
公开募捐{
//从网上下载图片
//待办事项
//如果下载成功
mDownloadListener.onDownloadComplete();
//如果下载时出错
mDownloadListener.onDownloadFailure();
//通知执行者经理任务已完成,可以启动新任务
递增计数();
}
私有静态同步的无效增量计数(){
ExecutorManager.getInstance().OnTaskCompleted();//有更好的方法吗
}
}
公共类执行器管理器{
私有静态执行器实例;
ExecutorService executor=Executors.newFixedThreadPool(常数.NumberOfParallelThread);
ArrayList ExecutorQueue=新的ArrayList();
int ActiveNumberOfThread=0;
私人遗嘱执行人(){
}
公共静态执行器管理器getInstance(){
if(实例==null){
实例=新的ExecutorManager();
}
返回实例;
}
私有void executeTask(){
if(ExecutorQueue.size()>0&&ActiveNumberOfThread
好吧,你很幸运。你什么都不必告诉经理。带有
BlockingQueue
ExecutorService
为您处理队列。您所要做的就是将
Runnable
提交给Executor服务。它会坚持下去的。如果有任何打开的线程,它将立即运行它。否则,它将等待另一个
可运行文件
完成执行。一旦它完成,它将采取下一个

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

public static ExecutorService newFixedThreadPool(int nThreads) {
         return new ThreadPoolExecutor(nThreads, nThreads,
                                       0L, TimeUnit.MILLISECONDS,
                                       new LinkedBlockingQueue<Runnable>());
} 
publicstaticexecutorservice newFixedThreadPool(int-nThreads){
返回新的ThreadPoolExecutor(第n个线程,第n个线程,
0L,时间单位为毫秒,
新建LinkedBlockingQueue());
}