2011-09-14 46 views
4

我试图在异步任务期间一个接一个地执行runnable队列(意味着队列中的下一个将在另一个完成后执行)。我编写了一个管理器来管理这些可自行运行的runnable和task。然后我在异步任务中获得第一个任务并运行它,希望它能够通过队列运行,但是它只是最终运行第一个runnable两次。任何人都可以用我一直在使用的代码来帮助我,或者指出一个可能有所帮助的例子吗?如何实现可运行队列

public class ConnectionManager { 

    public static final int MAX_CONNECTIONS = 15; 

    private ArrayList<Runnable> active = new ArrayList<Runnable>(); 
    private ArrayList<Runnable> queue = new ArrayList<Runnable>(); 

    private static ConnectionManager instance; 

    public static ConnectionManager getInstance() { 
     if (instance == null) 
      instance = new ConnectionManager(); 
     return instance; 
    } 

    public void push(Runnable runnable) { 
     queue.add(runnable); 
     if (active.size() < MAX_CONNECTIONS) 
      startNext(); 
    } 

    private void startNext() { 
     if (!queue.isEmpty()) { 
      Runnable next = queue.get(0); 
      queue.remove(0); 
      active.add(next); 

      Thread thread = new Thread(next); 
      thread.start(); 
     } 
    } 

    public void didComplete(Runnable runnable) { 
     active.remove(runnable); 
     startNext(); 
    } 
} 

public class Task implements Runnable { 
    Context con; 
    String xmlFile; 
    File taskFile; 
    String Id; 

    public void create(Context context, String xml, File task, String id) { 
     this.con = context; 
     this.xmlFile = xml; 
     this.taskFile = task; 
     this.Id = id; 
     ConnectionManager.getInstance().push(this); 
    } 

    @Override 
    public void run() { 
     User.SendTask(con, xmlFile, taskFile, Id); 

     ConnectionManager.getInstance().didComplete(this); 
    } 

回答

2

我在我的一个应用程序中做了非常类似的事情,我做的保持干净的是让我的队列包含数据而不是要执行的线程。我为我的执行使用了一个AsyncTask(从系统分配的线程池中提取...可能会让管理更容易),并且在它的doInBackground方法中,我将数据从队列中提取出来,对其进行操作,并在onPostExecute中再次调用我的入口方法。

2

有没有必要自己建立这个,只需使用ThreadPoolExecutor为你做。构建一个minPool大小为1,最大池大小为15的应用程序,并且应该全部设置。

+0

如果可运行对象累计超过十亿,会发生什么? – User3

2

为什么不使用Queue而不是ArrayLists?它会更适合在这里。

1

ArrayList不是线程安全的,但是您将它与线程一起使用。因此,你有不同的线程进入其他方式。以下是可能发生的事情:

  • 您使用各种可运行的程序调用多次推送。对于所有这些,add方法都会被同时调用,但由于add不是线程安全的,第一个在第二个开始添加之前没有完成添加,所以最终只有一个可以在队列中运行。

  • 然后StartNext被同时调用一堆。其中一个线程运行“next = queue.Get(),但是,另一个线程在第一个线程有机会从队列中删除该项目之前,还会调用”next = queue.Get()“,这样两个线程最终都会处理同样可运行。

你需要找到一条线程对象来使用,或增加一些类型的互斥锁/锁机制,以确保各线程不会在对方的方式获得。