- 48
- 0
问题描述
小弟在公司的项目中使用了list.spliterator()方法尝试将一个List<Map<String, Object>>对象按照一定的条件查询数据库,然后将查询的结果(是一个List对象)通过map.put()放进这个map中,但是通过线程池创建线程并执行后第一次会查询到正确结果,但是后面重复请求就没有put进去的集合了
小弟刚进入编程界不久对并发安全问题以及其它问题都还不熟悉,请各位大佬解答一下
问题出现的环境背景及自己尝试过哪些方法
我把Map<String, Object>换成了List<ConcurrentHashMap<String, Object>>也不行,我以为是list的问题,所以用了Collections.synchronizedList(list);
相关代码
//这是controller
public List<ConcurrentHashMap<String,Object>> test(@RequestBody List<ConcurrentHashMap<String,Object>> list){
final List<ConcurrentHashMap<String, Object>> concurrentHashMaps = Collections.synchronizedList(list);
List<ConcurrentHashMap<String, Object>> ListMap = calculateService.getListMap(concurrentHashMaps);
return ListMap;
}
//这是service
// 线程池我设置了线程数为4 并且countDownLatch也为4
public List<ConcurrentHashMap<String, Object>> getListMap(List<ConcurrentHashMap<String, Object>> list) {
// 将list四等分
Spliterator<ConcurrentHashMap<String, Object>> allList = list.spliterator();
Spliterator<ConcurrentHashMap<String, Object>> halfList = allList.trySplit();
Spliterator<ConcurrentHashMap<String, Object>> quarterAllList = allList.trySplit();
Spliterator<ConcurrentHashMap<String, Object>> quarterHalfList = halfList.trySplit();
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
RequestContextHolder.setRequestAttributes(servletRequestAttributes,true);
//将分好的List放进线程池
List<Spliterator<ConcurrentHashMap<String, Object>>> spliterators = Arrays.asList(allList, halfList, quarterAllList, quarterHalfList);
for (Spliterator<ConcurrentHashMap<String, Object>> spliterator : spliterators) {
if (ObjectUtil.isNotNull(spliterator)){
executor.execute(new SelectTask(taxInfoMapper,countDownLatch,spliterator));
}
}
try {
// 阻塞住主线程,等待任务完成
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return list;
}
public class SelectTask implements Runnable {
private TaxInfoMapper taxInfoMapper;
private CountDownLatch countDownLatch;
private Spliterator<ConcurrentHashMap<String, Object>> list;
public SelectTask(TaxInfoMapper taxInfoMapper, CountDownLatch countDownLatch, Spliterator<ConcurrentHashMap<String, Object>> list) {
this.taxInfoMapper = taxInfoMapper;
this.countDownLatch = countDownLatch;
this.list = list;
}
@Override
public void run() {
list.forEachRemaining(map -> {
String taxNo = (String) map.get("taxNo");
String deptNo = (String) map.get("deptNo");
String month = (String) map.get("month");
List<String> idList = (List<String>) map.get("idList");
// 这里我传进来一个mapper然后查询出一个对象List
List<TaxInfoBO> taxInfoBOS = taxInfoMapper.selectTaxInfoList(taxNo, deptNo, month, idList);
// 然后将他放在原先的map中
map.put("taxInfoList",taxInfoBOS);
countDownLatch.countDown();
});
}
}
你期待的结果是什么?
这是我的那个请求参数之一
{
"taxNo": "123124",
"month": "2019-12",
"deptNo": "1",
"idList":[
"310104198603042438",
"130130198907243027",
"330722199110014512",
"362322198903110046",
"330402198703161239",
"33062119820508869X",
"33262419880810002X",
"371002199204038253"
]
},
返回结果应该有一个taxInfoList - 共 0 条
- 全部回答
-
头头碰着黑 普通会员 1楼
在Java中,
List接口提供了一种遍历集合的容器,其中包含一个可迭代对象(如List<T>)和一个可调用方法next(),用于获取并返回当前迭代的下一个元素。List.spliterator()方法用于获取并返回列表的可迭代对象的迭代器,这个迭代器会遍历列表的所有元素,但不会创建一个新的列表,而是返回一个实现了Spliterator接口的对象,该对象可以在多线程环境中并发地访问列表的所有元素。以下是一个简单的示例,展示如何在多线程环境中使用
List.spliterator()方法:```java import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger;
public class MultiThreadedListSpliteratorExample { public static void main(String[] args) { // 创建一个包含10个元素的列表 List
list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); list.add(6); list.add(7); list.add(8); list.add(9); list.add(10); // 创建一个线程池,包含5个线程 ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个计数器,用于记录当前线程访问的元素数量 AtomicInteger count = new AtomicInteger(0); // 使用spliterator()方法获取列表的可迭代对象的迭代器 List<Integer> iterator = list.spliterator(); // 创建一个线程池的执行器,每个线程负责访问一个元素并更新计数器 for (int i = 0; i < 5; i++) { executor.execute(() -> { // 获取当前迭代的下一个元素 int element = iterator.next(); // 更新计数器 count.incrementAndGet(); // 在这里执行一些操作,如打印元素或执行其他耗时操作 System.out.println("Element " + element + " accessed, count: " + count.get()); }); } // 关闭线程池 executor.shutdown(); // 等待所有线程完成 while (!executor.isTerminated()) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } // 打印所有的元素和计数器 System.out.println("Elements accessed: " + list.size() + ", count: " + count.get()); }} ```
在这个示例中,我们首先创建了一个包含10个整数的
List。然后,我们创建了一个线程池,包含5个线程,每个线程负责访问一个元素并更新计数器。我们使用List.spliterator()方法获取列表的可迭代对象的迭代器,并将它赋值给iterator变量。然后,我们创建了一个线程池的执行器,每个线程负责访问一个元素并更新计数器。在每个线程中,我们首先获取当前迭代的下一个元素,然后更新计数器,并在System.out.println()方法中打印出元素和计数器的值。最后,我们关闭线程池,并等待所有线程完成。我们打印出所有的元素和计数器,以验证程序的行为。在多线程环境中,由于
List.spliterator()方法返回的是一个Spliterator对象,所以可以同时执行多个线程,每个线程都可以独立地访问列表中的元素,而不会阻塞其他线程。然而,由于线程安全的限制,不能在多线程环境中直接修改列表,所以要处理这种情况,通常需要使用一些同步机制,如Lock或ConcurrentHashMap,以确保在多个线程同时访问列表时的线程安全性。
- 扫一扫访问手机版
回答动态

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器更新之后。服务器里面有部分玩家要重新创建角色是怎么回事啊?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题函数计算不同地域的是不能用内网吧?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题ARMS可以创建多个应用嘛?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题在ARMS如何申请加入公测呀?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题前端小程序接入这个arms具体是如何接入监控的,这个init方法在哪里进行添加?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器刚到期,是不是就不能再导出存档了呢?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器的游戏版本不兼容 尝试更新怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器服务器升级以后 就链接不上了,怎么办?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器转移以后服务器进不去了,怎么解决?预计能赚取 0积分收益

- 神奇的四哥:发布了悬赏问题阿里云幻兽帕鲁服务器修改参数后游戏进入不了,是什么情况?预计能赚取 0积分收益
- 回到顶部
- 回到顶部
