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