有没有一种方法可以将多个线程添加到同一列表对象?

时间:2020-02-22 07:18:11

标签: java multithreading arraylist concurrency threadpool

我正在构建一个需要创建共享ArrayList对象的应用程序。它是一个多线程环境,因此所有线程都应写入同一列表。

我试图创建一个列表对象并传递给executorservice,但这将创建同一列表的多个副本,最后我只看到列表中添加了一项。

注意:我只关心异步编写列表。我的阅读已同步。

//If you want to use the following:
Provider.of<ButtonData>(context, listen: false).selectedButton = xyz;

//You need to declare a setter named `selectedButton` in your ButtonData
// class. Like so:

set selectedButton(Button button) {
    _selectedButton = button;
    notifyListeners();
}

//Currently, in your ButtonData class, you have not declared a setter,
// instead you created a method there for updating the value. 
//This one.

void setSelectedItem(Button s) {
    _selectedButton = s;
    notifyListeners();
}

//If you want to use this method for updating your `selectedButton` value,
// you can use the following line of code.
Provider.of<ButtonData>(context, listen: false).setSelectedItem(xyz);

如何使所有线程使用/写入同一List对象?

我是多线程技术的新手,将不胜感激。

谢谢。

更新:我尝试使用Collections.syncronizedList,但它仍然对我不起作用。可能是我没有正确使用它

public class main{
      public static void main(String[] args)
    {

        ExecutorService taskExec = Executors.newFixedThreadPool(count); 
        List<JsonDocument> documents = new ArrayList<JsonDocument>();

        // this seems to be incorrect
        taskExec.submit(new test(documents, size));
    }
}

class test implements Runnable{

// this class will add JsonDocuments to list object

}

请在这里纠正我。

2 个答案:

答案 0 :(得分:2)

Collections.syncronizedList应该可以完成工作,但是您的代码存在一些问题:

    taskExec.submit(new test(documents, size));

    for (JsonDocument json : documents) {
        System.out.println(json.toString());
    }


    while(!taskExec.isTerminated()) {
        taskExec.shutdown();
    }
  1. 您提交可运行对象,但不等待终止 打印列表

  2. while(!taskExec.isTerminated())不是 等待终止的正确方法

这是修改后的代码:

    taskExec.submit(new test(documents, size));

    taskExec.awaitTermination(1, TimeUnit.MINUTES);// wait a minute for termination

    for (JsonDocument json : documents) {
        System.out.println(json.toString());
    }

    // This should be inside a finally block
    taskExec.shutdown();

答案 1 :(得分:1)

for-loop取决于线程执行的操作。您必须等待所有线程完成执行。您可以使用Eugen建议的taskExec.awaitTermination。但是很难提出awaitTermination超时时间,您可以传递一些大的值,但是解决方案无法很好地扩展。

如果您使用的是Java 8或更高版本,请使用CompletableFuture

CompletableFuture.runAsync(new test(documents, size), taskExec2)
  .thenAccept(documents -> documents.forEach(doc -> System.out.print(doc.toString())));

如果您使用的是Java 7,则可以使用Future

Future<Void> future = taskExec.submit(new test(documents, size));
submit.get();  // blocking operation
// your logic for-loop etc.

测试班:

class test implements Callable<Void> {
   // constructor etc.

    public Void call() {    
       // your business logic

       return null;
    }
}

请注意, syncedList的结果是“ synchronized”,而不是“ concurrent”。许多基于索引的List操作本身不是原子的,这是一个基本问题,需要成为更大的互斥结构的一部分。