如何将RecursiveTask结果转换为ConcurrentMap?自定义SearchTask2实现问询
RecursiveTask<Map<Short, Long>> and Converting Results to ConcurrentMap Hey there! Let's work through your SearchTask2 implementation and the ConcurrentMap conversion requirement. Here's a complete, practical solution tailored to your code snippet:
1. Complete SearchTask2 Implementation
First, let's finish the SearchTask2 class. The core of any RecursiveTask is the compute() method—this is where we split large tasks into smaller chunks (when above your threshold) and merge results from sub-tasks.
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentNavigableMap; import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.RecursiveTask; public class SearchTask2 extends RecursiveTask<Map<Short, Long>> { private final int majorDataThreshold = 16000; private final ConcurrentNavigableMap<Short, Long> dataMap; private final long fromRange; private final long toRange; private final boolean fromInclusive; private final boolean toInclusive; // Constructor: Convert input Map to ConcurrentNavigableMap for safe parallel processing public SearchTask2(final Map<Short, Long> dataSource, final long fromRange, final long toRange, final boolean fromInclusive, final boolean toInclusive) { // Use ConcurrentSkipListMap for navigable features; swap to ConcurrentHashMap if you don't need ordering this.dataMap = new ConcurrentSkipListMap<>(dataSource); this.fromRange = fromRange; this.toRange = toRange; this.fromInclusive = fromInclusive; this.toInclusive = toInclusive; } @Override protected Map<Short, Long> compute() { // Calculate the size of the current range (adjust logic to match your actual range definition) long rangeSize = toRange - fromRange + (fromInclusive && toInclusive ? 1 : 0); // If range is small enough, process directly without splitting if (rangeSize <= majorDataThreshold) { ConcurrentMap<Short, Long> result = new ConcurrentHashMap<>(); // Filter entries that fall within the target range for (Map.Entry<Short, Long> entry : dataMap.entrySet()) { long value = entry.getValue(); boolean isInRange = false; // Handle inclusive/exclusive bounds logic if (fromInclusive && toInclusive) { isInRange = value >= fromRange && value <= toRange; } else if (fromInclusive) { isInRange = value >= fromRange && value < toRange; } else if (toInclusive) { isInRange = value > fromRange && value <= toRange; } else { isInRange = value > fromRange && value < toRange; } if (isInRange) { result.put(entry.getKey(), entry.getValue()); } } return result; } // Split the range into two sub-tasks for parallel processing long midRange = fromRange + (rangeSize / 2); SearchTask2 leftTask = new SearchTask2(dataMap, fromRange, midRange, fromInclusive, false); SearchTask2 rightTask = new SearchTask2(dataMap, midRange, toRange, true, toInclusive); // Fork the left task to run asynchronously leftTask.fork(); // Compute the right task synchronously, then wait for the left task's result Map<Short, Long> rightResult = rightTask.compute(); Map<Short, Long> leftResult = leftTask.join(); // Merge results into a ConcurrentMap to ensure thread safety during merging ConcurrentMap<Short, Long> mergedResult = new ConcurrentHashMap<>(rightResult); mergedResult.putAll(leftResult); return mergedResult; } }
2. Converting RecursiveTask Results to ConcurrentMap
There are two clean, efficient ways to handle this:
Option 1: Return ConcurrentMap Directly (Recommended)
Modify the task's return type to ConcurrentMap<Short, Long> instead of Map—this eliminates the need for post-conversion entirely, which is the most performant approach:
public class SearchTask2 extends RecursiveTask<ConcurrentMap<Short, Long>> { // ... rest of the code remains nearly identical; just return ConcurrentMap instances in compute() }
Option 2: Convert After Task Completion
If you need to keep the Map return type, convert the result once the task finishes executing:
// Execute the task SearchTask2 task = new SearchTask2(yourDataSource, 0L, 100000L, true, true); Map<Short, Long> resultMap = task.invoke(); // Convert to ConcurrentHashMap ConcurrentMap<Short, Long> concurrentResult = new ConcurrentHashMap<>(resultMap); // Or to ConcurrentSkipListMap if you need navigable/ordered features ConcurrentNavigableMap<Short, Long> navigableConcurrentResult = new ConcurrentSkipListMap<>(resultMap);
Key Notes
- Thread Safety: Using
ConcurrentMapfor intermediate and final results ensures safe merging of sub-task outputs—critical for reliable parallel processing. - Threshold Tuning: Adjust
majorDataThresholdbased on performance testing. Too small and you'll get excessive task overhead; too large and you won't leverage parallelism effectively. - Range Logic: Double-check the range filtering logic in
compute()to match your exact inclusive/exclusive bound requirements.
内容的提问来源于stack exchange,提问作者edwin

