Java CompletableFuture将结果收集到hashmap
我正在从数据库中读取pdf文件列表,并对其进行解析,并使用它们执行一些任务。Java CompletableFuture将结果收集到hashmap,java,multithreading,concurrency,completable-future,concurrenthashmap,Java,Multithreading,Concurrency,Completable Future,Concurrenthashmap,我正在从数据库中读取pdf文件列表,并对其进行解析,并使用它们执行一些任务。 当我阅读这个pdf列表时,我看到从pdf中提取图像需要花费更多的时间,我不需要阻止我的主线程来阅读图像。所以我想在一个单独的线程中执行提取图像。 我想从一个又一个pdf文件中读取图像,而不需要一次将所有pdf文件加载到内存中(由于内存问题)。所以我只需要2个线程;一个应该是主线程(从pdf中读取一些文本并执行其他操作),另一个应该是提取图像并返回图像对象集的线程 这里需要注意的一点是,PDF中的图像在内容上可能相同,因
当我阅读这个pdf列表时,我看到从pdf中提取图像需要花费更多的时间,我不需要阻止我的主线程来阅读图像。所以我想在一个单独的线程中执行提取图像。
我想从一个又一个pdf文件中读取图像,而不需要一次将所有pdf文件加载到内存中(由于内存问题)。所以我只需要2个线程;一个应该是主线程(从pdf中读取一些文本并执行其他操作),另一个应该是提取图像并返回图像对象集的线程 这里需要注意的一点是,PDF中的图像在内容上可能相同,因此我希望在收集其结果之前,使用校验和或其他方法删除重复的图像。
我不希望在所有任务完成之前将图像保存在内存中,我希望在获得一个pdf的结果时删除重复的图像 所以真正的问题是,我需要将多个任务提交到一个大小为1的线程池,并且需要在得到结果时删除重复的任务,这样我就不需要在内存中保存图像更长的时间 下面是我尝试过的想法。
我已经从代码中删除了不必要的东西,比如图像及其内容,并将代码转换为基于字符串的问题
public static void main(String[] args) throws InterruptedException, ExecutionException {
Map<String, Integer> uniqueImages = new HashMap<>();
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1);
List<CompletableFuture<String>> futureList = new ArrayList<>();
for(int i = 0; i<20000; i++) {
CompletableFuture<String> obj = CompletableFuture.supplyAsync(()->{
//Assume lot of duplicates
return UUID.randomUUID().toString();
}, newFixedThreadPool).thenApply((x)->{
if(uniqueImages.containsKey(x)) {
int val = uniqueImages.get(x);
uniqueImages.put(x, val+1);
}
else {
uniqueImages.put(x, 1);
}
return x;
});
futureList.add(obj);
}
for(CompletableFuture<String> future: futureList) {
future.get();
}
System.out.println(uniqueImages.size());
}
publicstaticvoidmain(String[]args)抛出InterruptedException、ExecutionException{
Map uniqueImages=newhashmap();
ExecutorService newFixedThreadPool=Executors.newFixedThreadPool(1);
List futureList=新建ArrayList();
对于(int i=0;i{
//假设有很多重复的
返回UUID.randomUUID().toString();
},newFixedThreadPool)。然后应用((x)->{
if(uniqueImages.containsKey(x)){
int val=uniqueImages.get(x);
uniqueImages.put(x,val+1);
}
否则{
唯一图像。放置(x,1);
}
返回x;
});
添加(obj);
}
用于(可完成的未来:未来列表){
future.get();
}
System.out.println(uniqueImages.size());
}
我担心这段代码是否真的有效或引发ConcurrentModification异常
map是否真的包含唯一的图像及其计数uniqueImages
- 有什么隐藏的问题吗
- 有更好的方法来解决我的用例吗
我们可以使用以下场景进行演示: 考虑以下代码:
if(uniqueImages.containsKey(x)){
int val=uniqueImages.get(x);
uniqueImages.put(x,val+1);
}
否则{
唯一图像。放置(x,1);
}
假设线程1和线程2都返回相同的字符串,并到达第if行(uniqueImages.containsKey(x))
。if
将在两个线程中返回false,并且uniqueImages.put(x,1)代码>将在两个线程中调用。
将引发ConcurrentModification
异常,或者您将得到错误的计数(1而不是2)
如果您计划使用多个线程,那么您必须使用ConcurrentHashMap
好吧,我肯定会使用ConcurrentHashMap
代替HashMap
进行将来的校对。如果您增加线程池中的线程数,那么它通常会给出错误的大小。其次,作为参考,然后应用
可以在同一线程上执行,也可以不在同一线程上执行。