Java JSONArray迭代并行化实现需求及代码优化问询
嘿,针对你这段需要并行化的JSON数组遍历代码,我给你几个实用的Java实现方案——毕竟你的操作相互独立,完全是并行处理的绝佳场景😉:
并行化JSON数组遍历的几种Java实现方案
方案1:使用Java 8+ Stream API(最简洁省心)
Stream API的并行流(parallelStream)是处理这类场景的首选,JVM会自动帮你管理线程池,不用手动折腾线程逻辑。不过有个关键细节要注意:你原来定义的ArrayList<StockQuote> topGainers不是线程安全集合,如果直接在并行操作里调用topGainers.add(),大概率会出现并发问题。推荐用下面两种方式解决:
方式A:用Stream收集器生成结果(更推荐)
这种方式内部会自动处理线程安全,代码也更简洁:
List<StockQuote> topGainers; JSONObject jsonObject = (JSONObject) new JSONParser().parse(new InputStreamReader(response.getEntity().getContent(), "UTF-8")); JSONArray dataArray = (JSONArray) jsonObject.get("data"); // 并行遍历并收集结果 topGainers = IntStream.range(0, dataArray.size()) .parallel() .mapToObj(iter -> { JSONObject temp = (JSONObject) dataArray.get(iter); // 这里写你原来的处理逻辑,比如解析temp为StockQuote对象 StockQuote quote = parseStockQuote(temp); // 假设你有这个解析方法 System.out.println(quote); // 你的打印逻辑 return quote; }) .collect(Collectors.toList());
方式B:改用线程安全集合
如果你一定要保留原来的集合引用,可以换成CopyOnWriteArrayList这类线程安全的实现:
List<StockQuote> topGainers = new CopyOnWriteArrayList<>(); JSONObject jsonObject = (JSONObject) new JSONParser().parse(new InputStreamReader(response.getEntity().getContent(), "UTF-8")); JSONArray dataArray = (JSONArray) jsonObject.get("data"); // 并行遍历并添加元素 IntStream.range(0, dataArray.size()).parallel().forEach(iter -> { JSONObject temp = (JSONObject) dataArray.get(iter); StockQuote quote = parseStockQuote(temp); topGainers.add(quote); System.out.println(quote); });
要是你需要自定义线程池大小(比如不想用默认的公共池),还可以用ForkJoinPool来包装并行流:
// 指定4个线程的自定义池 ForkJoinPool customPool = new ForkJoinPool(4); List<StockQuote> topGainers = customPool.submit(() -> IntStream.range(0, dataArray.size()) .parallel() .mapToObj(iter -> { JSONObject temp = (JSONObject) dataArray.get(iter); return parseStockQuote(temp); }) .collect(Collectors.toList()) ).join(); customPool.shutdown(); // 用完记得关闭池
方案2:使用ExecutorService手动管理线程池
如果需要更精细地控制线程参数(比如核心线程数、队列大小),或者要兼容Java 8之前的版本,可以手动用线程池实现:
List<StockQuote> topGainers = new ArrayList<>(); JSONObject jsonObject = (JSONObject) new JSONParser().parse(new InputStreamReader(response.getEntity().getContent(), "UTF-8")); JSONArray dataArray = (JSONArray) jsonObject.get("data"); // 创建固定大小的线程池,大小设为CPU核心数是比较合理的选择 ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); List<Future<StockQuote>> futures = new ArrayList<>(); // 提交所有并行任务 for (int iter = 0; iter < dataArray.size(); iter++) { final int index = iter; // 匿名内部类需要引用final变量 futures.add(executor.submit(() -> { JSONObject temp = (JSONObject) dataArray.get(index); StockQuote quote = parseStockQuote(temp); System.out.println(quote); return quote; })); } // 等待所有任务完成,收集结果 for (Future<StockQuote> future : futures) { try { topGainers.add(future.get()); } catch (InterruptedException | ExecutionException e) { // 记得处理异常,比如打印日志或者做降级处理 e.printStackTrace(); } } // 用完线程池一定要关闭 executor.shutdown();
几个关键注意事项
- 线程安全优先:只要涉及共享集合的修改,一定要用线程安全的实现,或者依赖Stream收集器的线程安全机制,不然会出现数据错乱的问题。
- 异常别忽略:并行处理时的异常容易被隐藏,比如Stream并行流会抛出
CompletionException,Future需要捕获ExecutionException,一定要妥善处理。 - 别盲目并行:如果你的JSON数组元素很少(比如少于100个),并行处理的线程开销可能会抵消性能收益,建议在数据量较大的时候再用并行。
内容的提问来源于stack exchange,提问作者Prateek Narendra
相关产品推荐
相关产品推荐

