Java 如何以多线程方式调用返回列表元素的方法

Java 如何以多线程方式调用返回列表元素的方法,java,multithreading,arraylist,Java,Multithreading,Arraylist,我有这个方法: public List<String> composeList (DataBaseObject dBO) { List<String> valueList = new ArrayList<>(); for (String separatedFieldName : separatedFieldNames) { object = PropertyUtils.getProperty(object,

我有这个方法:

    public List<String> composeList (DataBaseObject dBO) {
    List<String> valueList = new ArrayList<>();
       for (String separatedFieldName : separatedFieldNames) {
           object = PropertyUtils.getProperty(object, separatedFieldName);
           valueList.add(object.toString());
       }                        
    }
public List composeList(数据库对象dBO){
List valueList=新的ArrayList();
for(字符串分隔字段名:分隔字段名){
object=PropertyUtils.getProperty(对象,分隔字段名);
valueList.add(object.toString());
}                        
}
我有一个1000个dBO对象的列表,并且希望以多线程的方式调用这个方法

但是这个方法的返回也会进入一个列表

这是来电者:

List<List<String>> valueLists =  new ArrayList<>();
    for (DataBaseObject dBO : listOfDBOs)
    valueLists.add(composeList(dBOObject));
List valueLists=new ArrayList();
for(数据库对象dBO:listOfDBOs)
添加(composeList(dBOObject));
由于现在的机器有多个核心,我想知道如何使用它们。比如如何在Parelle中调用composeList并将结果存储在一个ArrayList中

我知道我可以使用Collections.SynchronizedList,但是composeList的执行时间太少了,我最终会按顺序添加元素,即使是多线程的,它仍然是按顺序执行的,因为每次添加都会锁定Sysnchronized列表


这听起来像是一个设计问题,但仍然与编程有关。我真的很感激你能帮我解决这个问题

阅读java中的
ExecutorService
ForkJoin
框架。它可以帮助你实现你想要的

List<String> dbFieldValues = dbObjectList.parallelStream()
    .flatMap(seperatedFieldNames().parallelStream()
        .map(fn -> PropertyUtils.getProperty(db, fn).toString()))
    .collect(Collectors.toList());

多谢各位

Java 8并行流正是针对这种情况而设计的

List<String> dbFieldValues = dbObjectList.parallelStream()
    .flatMap(seperatedFieldNames().parallelStream()
        .map(fn -> PropertyUtils.getProperty(db, fn).toString()))
    .collect(Collectors.toList());
List dbFieldValues=dbObjectList.parallelStream()
.flatMap(单独的字段名().parallelStream())
.map(fn->PropertyUtils.getProperty(db,fn.toString())
.collect(Collectors.toList());
假设
单独的字段名集合
支持并行流(例如
ArrayList
),这将使用多个线程,而无需自己创建它们


请注意,这假设对
getProperty
没有任何副作用,这个解决方案可能有点“传统风格”,没有任何酷的新东西,如流等,但我会做如下操作:

public class AnyClass {

    private static final AtomicInteger index = new AtomicInteger(0);
    private static final Object lock = new Object();      

    public class ComposerThread implements Runnable {

        private List<DataBaseObject> dboList;
        private List<List<String>> valueList;
        private List<String> fieldNames;

        public MyThread(List<DataBaseObject> dboList, List<List<String>> valueList, 
                        List<String> fieldNames) {
            this.valueList= valueList;
            this.dboList = dboList;
            this.fieldNames = fieldNames;
        }

        public void run() {
            int i = index.getAndIncrement(); //thread takes next unprocessed index
            while(i<dboList.size()){
                DataBaseObject object = dboList.get(i);
                List<String> list = new ArrayList<>();
                for (String separatedFieldName : fieldNames) {
                    Object object = PropertyUtils.getProperty(object, separatedFieldName);
                    list.add(object.toString());
                }  

                synchronized (lock) {  //addition synchronized
                    valueList.add(list);
                }
                i = index.getAndIncrement(); //thread takes next unprocessed index
            }
        }
    }
    ....
}

如您所见,您甚至可以设置线程数。

我认为您不能同时安全地写入对象。您可以在运行另一个任务时调用列表填充器,但不能让两个任务同时编辑同一个列表。这就是为什么SynchronizedList在这样使用时基本上是顺序行为,这是唯一安全的方法。就像我说的,这不一定是列表填充的问题。。也许你也可以对设计提出一些建议。不幸的是,我必须等待列表填充完成,才能执行下一个任务。所以不能同时调用其他任何东西。在您的示例中,不清楚为什么添加到
valueList
是在循环之外。据我所知,您要添加所有字段的所有值吗?@KenBekov哦,很抱歉,这是一个输入错误。您的答案是正确的,但不幸的是,至少目前我无法将应用程序迁移到使用Java8