【问题标题】:How can I add items to a list from a thread and keep the adding order?如何将项目从线程添加到列表并保持添加顺序?
【发布时间】:2013-04-11 12:39:44
【问题描述】:

我正在尝试在列表中添加一些项目并保持添加顺序。问题是 添加部分是在一个线程中完成的,因为我需要从数据库中获取一些详细信息,将它们放在一个
项目并将其添加到列表中。

public void addNewItem(Step item){

    Thread t = new Thread(new Runnable(){
        public void run() {
            item.setDetails(db.getStepDetails(step.getId()));
            add(item);
        }
    });

    t.start();
}

add 方法如下所示:

private void add(Step step){
    mitems.add(step);
}

如果我做类似的事情

 addNewItem(stepA);
 addNewItem(stepB);

如果第一次调用花费太多时间,第二个项目将首先添加到我的列表中。

您知道如何等待操作完成后再继续在我的列表中添加任何其他项目吗?

谢谢。

【问题讨论】:

  • 我可能错了,但我相信使用synchronize 可以解决这个问题
  • 您真的要使用单独的线程吗?在您的情况下,您恰好需要按顺序执行指令。
  • 一种解决方法是同步 id,每次添加时都会增加并存储在添加的项目中。然后,您可以在生成的容器中看到项目的添加顺序。

标签: java android multithreading


【解决方案1】:

您可以添加同步块或使用 ReentrantLock。

Thread t = new Thread(new Runnable(){
    public void run() {
        synchronized(someSafeVar) {
            item.setDetails(db.getStepDetails(step.getId()));
            add(item);
        }
    }
});

另外,如果只是“add”方法需要时间,则只能同步该方法。

【讨论】:

    【解决方案2】:

    您可以创建单个工作线程,并从队列中提供它,这样您就可以将单个线程添加到 mitems 中。

    在这种情况下,您需要创建两个列表,并将它们同步。

    例如,

    List<Step> processingList = new ArrayList<Step>();
    List<Step> mitems = new ArrayList<Step>();
    public void addNewItem(Step item)
    {
      syncrhonized(processingList)
      {
        processingList.add(item);
      }
    }
    

    工作线程从 processingList 前面获取项目,处理它们,并在它们准备好时将它们添加到 mitem。

    【讨论】:

    • 我建议使用 Queue 来处理列表,因为将项目添加到末尾并从头开始检索它们对于使用队列来说是典型的
    【解决方案3】:

    您可以改用字典:

    Dictionary mitems = new Hashtable();
    

    mitems.put("1", item);
    

    那么关键就是秩序。

    【讨论】:

      【解决方案4】:

      如果您在设置详细信息之前将商品添加到列表中,您可以保持商品顺序。 然后您可以等待所有以下操作,直到设置您的项目的初始化标志:

      mitems.add(stepA);
      mitems.add(stepB)
      
      [...]
      
      ThreadGroup group = new ThreadGroup("GetStepDetailsGroup");
      
      for(Step step : mitems)
      {
          Thread thread = new Thread(group, new Runnable(){
              public void run() {
                  item.setDetails(db.getStepDetails(step.getId()));
              }
          });
      
          thread.start();
      }
      
      while(group.activeCount() > 0) {
          try {
              Thread.sleep(50);
          } catch(InteruptedExpection e) {
              // ignored
          }
      }
      

      【讨论】:

        【解决方案5】:

        在您的示例中,将步骤添加到列表似乎完全独立于从数据库中检索信息和填写步骤。

        因此,您可以只使用一个线程将所有步骤放在一个列表中。然后,您将使用 Runnables 获取 DB 信息,每个 Step 一个,并在 Executor 中使用任意数量的线程执行这些 Runnables(同时仍然从多线程中获得加速)。

        【讨论】:

          【解决方案6】:

          Thread#join

          等待此线程终止。

          希望这会有所帮助, 亚龙

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-07
            • 1970-01-01
            • 1970-01-01
            • 2018-04-04
            • 1970-01-01
            • 2017-07-14
            相关资源
            最近更新 更多