CompletableFutures 不起作用的 Groovy 异步合并方法

问题描述 投票:0回答:1

我有这个

SheetMerger
,它有这种异步合并
SheetModel
的方法。这些
SheetModel
本身就是从不同的表格中异步获取的结果,有些表格有数千行,有些只有几行。

我想按完成顺序合并结果。

这里是运行该方法所需的所有代码

merge

public class SheetMerger {
    public SheetModel merge(List<Future<SheetModel>> promises) { 
        List<String> mergedInColumnNames = [];
        String keyColumnName;
        List<Map<String, Object>> mergedInData = [];
        
        CompletableFuture[] promisesArray = new CompletableFuture[promises.size()];
        for (int idx = 0; idx < promisesArray.size(); idx++)
            promisesArray[idx] = promises[idx];
        
        CompletableFuture.anyOf(promisesArray).get();
        
        promisesArray.eachWithIndex { CompletableFuture<SheetModel> promise, int idx ->
            println "Starting to merge Sheet number ${idx + 1}"
            
            return promise.thenAcceptAsync { SheetModel model ->
                println "Merging Sheet number ${idx + 1}"
                
                mergedInColumnNames = CollectionUtils.MergeLists(mergedInColumnNames, model.columnNames);
                
                if (keyColumnName == null)
                    keyColumnName = model.keyColumnName;
                
                mergedInData = mergeIntoDataSource(mergedInData, keyColumnName, model);
                
                println "Sheet number ${idx + 1} merged"
            }
        
        }
        
        CompletableFuture.allOf(promisesArray).get();
            
        
        return new SheetModel(mergedInColumnNames, keyColumnName, mergedInData);
    }
    
    public List<Map<String, Object>> mergeIntoDataSource(List<Map<String, Object>> masterDataSource, String masterKey, SheetModel branchModel) {  
        
        branchModel.data.eachWithIndex { Map<String, Object> branchRow, int idx ->  
            Map<String, Object> masterRow = branchRow.findResult { String key, Object value -> 
                if (!key.equals(branchModel.keyColumnName))
                    return null;
                
                return masterDataSource
                    .find { Map<String, Object> row -> return row[masterKey].equals(value) }
            }
            
            if (masterRow == null) {
                masterDataSource.push(branchRow);
                return;
            }
                
            masterDataSource[idx] = CollectionUtils.MergeMaps(masterRow, branchRow);
        }
        
        
        return masterDataSource;
    }
    
}

public final class CollectionUtils {
    /**
     * **TODO**: bring in some callback that takes masterMap, branchMap, key, and defines a merge strategy
     * @param masterMap
     * @param branchMap
     * @return
     */
    public static Map MergeMaps(Map masterMap, Map branchMap) { 
        final List<String> listOfKeys = this.MergeLists(masterMap.keySet().toList(), 
            branchMap.keySet().toList());
        
        for (String key : listOfKeys) { 
            if (!branchMap.containsKey(key))
                continue;
                
            final Object branchValue = branchMap[key]; 
            if ((branchValue == null) || (branchValue.toString().trim().equals("")))
                continue;
            
            if ((!masterMap.containsKey(key)) || (masterMap[key].toString().trim().equals("")))
                masterMap[key] = branchValue;
        }
        
        return masterMap;
    }
    
    public static List MergeLists(List masterList, List... branchLists) { 
        return masterList.plus(branchLists)
            .flatten()
            .unique()
    }
}


在运行时,我没有看到 any 行说工作表已被合并(即实际的工作表合并似乎没有发生)。

这是我看到的:

reading the Sheets...
merging the Sheets..
Reading Sheet 'ZohoSPOS Reconciliation' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho_spos_balance-11_42_20_01_2023_WORKING.xlsx'...
Reading Sheet 'Corrections' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho-spos-balance-changes-v3.xlsx'...
Reading Sheet 'ZohoSPOS Reconciliation' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho_spos_balance-08_25_30_12_2022.xlERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
Sheet 'Corrections' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho-spos-balance-changes-v3.xlsx' has been parsed!
Reading Sheet 'Robert' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho-spos-balance-changes-v1.xlsx'...
Starting to merge Sheet number 1
Starting to merge Sheet number 2
Starting to merge Sheet number 3
Starting to merge Sheet number 4
Starting to merge Sheet number 5
Sheet 'Robert' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho-spos-balance-changes-v1.xlsx' has been parsed!
Merging Sheet number 4
Reading Sheet 'Sheet1' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho-spos-balance-changes-v1.xlsx'...
Sheet 'Sheet1' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho-spos-balance-changes-v1.xlsx' has been parsed!
Merging Sheet number 5
Merging Sheet number 2
Sheet 'ZohoSPOS Reconciliation' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho_spos_balance-08_25_30_12_2022.xlsx' has been parsed!
Merging Sheet number 3
Sheet 'ZohoSPOS Reconciliation' in Excel file 'C:\Users\Eliza\Desktop\Upwork jobs\job\com.job.sposZohoMergeScript\excelSourceFiles\zoho_spos_balance-11_42_20_01_2023_WORKING.xlsx' has been parsed!
Merging Sheet number 1

groovy completable-future
1个回答
0
投票

原来我需要

synchronized
关键字。将我的
SheetMerger
代码更改为此解决了问题:

public class SheetMerger {

    synchronized List<String> mergedInColumnNames;
    synchronized List<Map<String, Object>> mergedInData
    
    
    public SheetModel merge(List<Future<SheetModel>> promises) { 
        final SheetModel firstSheetModel = AsyncUtils.AwaitFirstResolvingPromise(promises);
        
        mergedInColumnNames = firstSheetModel.columnNames;
        mergedInData = firstSheetModel.data;
        String keyColumnName = firstSheetModel.keyColumnName;
        
        CompletableFuture<SheetModel>[] promisesArray = new CompletableFuture<SheetModel>[promises.size()];
        for (int idx = 0; idx < promisesArray.size(); idx++)
            promisesArray[idx] = promises[idx];
        
        promisesArray.eachWithIndex { CompletableFuture<SheetModel> promise, int idx ->
            println "Starting to merge Sheet number ${idx + 1}"
            
            promisesArray[idx] = promise.thenAcceptAsync { SheetModel model ->
                println "Merging Sheet number ${idx + 1}"
                
                mergedInColumnNames = CollectionUtils.MergeLists(mergedInColumnNames, model.columnNames);
                
                mergedInData = mergeIntoDataSource(mergedInData, keyColumnName, model);
                
                println "Sheet number ${idx + 1} merged"
            }
        
        }
        
        CompletableFuture.allOf(promisesArray).get();
        
        return new SheetModel(mergedInColumnNames, keyColumnName, mergedInData);
    }

    // helper method unchanged
}

出于某种奇怪的原因,我不得不手动创建

CompletableFuture[]
,并在使用集合的方法中写入每个最后的数组成员,这是我使用
CompletableFuture.allOf(collection).get()
的唯一方法......我不明白为什么...

© www.soinside.com 2019 - 2024. All rights reserved.