请教一个关于forkjoin的问题

白白了白呀白 2019-04-11 02:48:58
比如现在有个功能要找出所有馆子以及每个馆子下的所有菜品,我原先是用for循环遍历求出每个馆子下的菜品,然后把对应的馆子名和该馆子下的菜品列表放入map中,遍历完返回给前端,测试用时需要1秒多。然后我想能不能用forkjoin的方法,把遍历的这块分给多个任务去执行最终返回合并的结果,然后返回给前端。代码写完,发现用时反而增多1倍左右,请教下是什么原因呢?下面是我forkjoin中的代码

ConcurrentSkipListMap<String, Object> linkedHashMap = new ForkJoinPool().invoke(new FrSetGymTask(new ConcurrentSkipListMap<String, Object>(), maps, 0, maps.size()));


public class FrSetGymTask extends RecursiveTask<ConcurrentSkipListMap<String, Object>> {

/**
* 馆子列表及各馆子下的菜品列表
*/
private ConcurrentSkipListMap<String, Object> skipListMap;
/**
* 菜品列表
*/
private List<Map<String, String>> maps;
private int start;
private int end;

public FrSetGymTask(ConcurrentSkipListMap<String, Object> skipListMap, List<Map<String, String>> maps, int start, int end) {
this.skipListMap = skipListMap;
this.maps = maps;
this.start = start;
this.end = end;
}

@Override
protected ConcurrentSkipListMap<String, Object> compute() {
if (end - start < 5) {
for (int i = 0; i < maps.size(); i++) {
Map<String, String> map = maps.get(i);
if (map != null) {
// 查找对应场馆的项目列表
FrSetGymDao frSetGymDao = (FrSetGymDao)SpringUtils.getBean("frSetGymDao");
List<Map<String, String>> list = frSetGymDao.findListByModelId(map.get("id"));
skipListMap.put(map.get("navName"), list);
}
}
} else {
//分隔任务
int middle = (start + end) / 2;
FrSetGymTask left = new FrSetGymTask(skipListMap, maps, start, middle);
FrSetGymTask right = new FrSetGymTask(skipListMap, maps, middle + 1, end);
left.fork();
right.fork();
left.join();
right.join();
}
return skipListMap;
}
}

我个人思考造成用时反而增多是否跟map有关,想请教下还有更好的方式能缩短用时吗?代码层面
...全文
140 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
bcsflilong 2019-04-11
  • 打赏
  • 举报
回复
这个我怎么跟你解释呢 简单的说 你这个不是分布式,

你电脑或者服务器性能(CPU 内存 IO等)一定,你分配在多任务也是这一定量的性能下执行,不见的就会比单线程快


你要修一段路,前提是就你一个人修,你从头到尾修,一定必你分开几段穿插修快,因为中间状态切换也是耗时的
白白了白呀白 2019-04-11
  • 打赏
  • 举报
回复
引用 4 楼 maradona1984 的回复:
全内存操作,多线程其实不见得比单线程快,可以参考redis
谢谢
白白了白呀白 2019-04-11
  • 打赏
  • 举报
回复
引用 3 楼 LCL_data 的回复:
[quote=引用 2 楼 qq389203946 的回复:] [quote=引用 1 楼 LCL_data 的回复:] if (end - start < 5) { for (int i = 0; i < maps.size(); i++) { Map<String, String> map = maps.get(i); if (map != null) { // 查找对应场馆的项目列表 FrSetGymDao frSetGymDao = (FrSetGymDao)SpringUtils.getBean("frSetGymDao"); List<Map<String, String>> list = frSetGymDao.findListByModelId(map.get("id")); skipListMap.put(map.get("navName"), list); } } } end和start差距是5的时候进行计算,但是你计算的是全部的map参与计算的,没有用到start和end,这相当于你细分的越多,时间越久哟
你的意思是我每次分隔任务后 for (int i = 0; i < maps.size(); i++) 这一步的范围需要在我分隔的范围内是么 for (int i = start; i < end; i++)这样么[/quote] 对呀,你现在的只是执行了N次,每次都说全部 map执行一遍[/quote] 谢谢,不过好像数据有变少,是不是有线程安全问题
maradona1984 2019-04-11
  • 打赏
  • 举报
回复
全内存操作,多线程其实不见得比单线程快,可以参考redis
十八道胡同 2019-04-11
  • 打赏
  • 举报
回复
引用 2 楼 qq389203946 的回复:
[quote=引用 1 楼 LCL_data 的回复:] if (end - start < 5) { for (int i = 0; i < maps.size(); i++) { Map<String, String> map = maps.get(i); if (map != null) { // 查找对应场馆的项目列表 FrSetGymDao frSetGymDao = (FrSetGymDao)SpringUtils.getBean("frSetGymDao"); List<Map<String, String>> list = frSetGymDao.findListByModelId(map.get("id")); skipListMap.put(map.get("navName"), list); } } } end和start差距是5的时候进行计算,但是你计算的是全部的map参与计算的,没有用到start和end,这相当于你细分的越多,时间越久哟
你的意思是我每次分隔任务后 for (int i = 0; i < maps.size(); i++) 这一步的范围需要在我分隔的范围内是么 for (int i = start; i < end; i++)这样么[/quote] 对呀,你现在的只是执行了N次,每次都说全部 map执行一遍
白白了白呀白 2019-04-11
  • 打赏
  • 举报
回复
引用 1 楼 LCL_data 的回复:
if (end - start < 5) { for (int i = 0; i < maps.size(); i++) { Map<String, String> map = maps.get(i); if (map != null) { // 查找对应场馆的项目列表 FrSetGymDao frSetGymDao = (FrSetGymDao)SpringUtils.getBean("frSetGymDao"); List<Map<String, String>> list = frSetGymDao.findListByModelId(map.get("id")); skipListMap.put(map.get("navName"), list); } } } end和start差距是5的时候进行计算,但是你计算的是全部的map参与计算的,没有用到start和end,这相当于你细分的越多,时间越久哟
你的意思是我每次分隔任务后 for (int i = 0; i < maps.size(); i++) 这一步的范围需要在我分隔的范围内是么 for (int i = start; i < end; i++)这样么
十八道胡同 2019-04-11
  • 打赏
  • 举报
回复
if (end - start < 5) { for (int i = 0; i < maps.size(); i++) { Map<String, String> map = maps.get(i); if (map != null) { // 查找对应场馆的项目列表 FrSetGymDao frSetGymDao = (FrSetGymDao)SpringUtils.getBean("frSetGymDao"); List<Map<String, String>> list = frSetGymDao.findListByModelId(map.get("id")); skipListMap.put(map.get("navName"), list); } } } end和start差距是5的时候进行计算,但是你计算的是全部的map参与计算的,没有用到start和end,这相当于你细分的越多,时间越久哟

81,091

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧