HashMap&&Redis Concurrent Problem
2015-07-20 16:16
585 查看
1.前几天修改一个bug的时候发现一个Java数据结果并发的问题。大致过程如下:
其中Bean的数据结果如下,其中包含一个Map,主要是为了记录用户的使用次数。
Runnable:
Action:
MainClass:
出现的问题,启动的一百个线程中并不是没有count都被记录下来,主要原因是因为HashMap这种数据结构在并发的时候存在一定的问题,但是如何解决这个问题,最后采用了Redis Hash Map的数据结构记录了用户的使用,经测试不会出现并发问题。主要原因是Redis是个单线程运行的程序,其中HashMap并不会出现这个并发的问题。
2.曾宪杰 大型网站系统与Java中间件实践
在这个本书中举出一个例子,跟这个很相似,如下:
这个方法虽然能够正确的计数,但是在高并发的时候,却十分的影响性能,效率不高。将Map换成ConcurrentHashMap这个结构,代码如下:
这样的写法显然会造成高并发的线程的问题。
—-路漫漫其修远兮,吾将上下而求索!
其中Bean的数据结果如下,其中包含一个Map,主要是为了记录用户的使用次数。
public class Bean { private Map<String,String> map = new HashMap<String,String>(); private String userId; private int count = 0; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + count; result = prime * result + ((map == null) ? 0 : map.hashCode()); result = prime * result + ((userId == null) ? 0 : userId.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Bean other = (Bean) obj; if (count != other.count) return false; if (map == null) { if (other.map != null) return false; } else if (!map.equals(other.map)) return false; if (userId == null) { if (other.userId != null) return false; } else if (!userId.equals(other.userId)) return false; return true; } @Override public String toString() { return "Bean [map=" + map + ", userId=" + userId + ", count=" + count + "]"; } public Map<String, String> getMap() { return map; } public void setMap(Map<String, String> map) { this.map = map; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub } }
Runnable:
public class TaskRunnable implements Runnable{ private int operationNumber; public TaskRunnable(int a){ this.operationNumber = a; } @Override public void run() { Action action = new Action(); Bean bean = action.getAndUpdateBeanFromCache(); System.out.println("threadId is id = " + Thread.currentThread().getId()); if(bean==null){ bean = new Bean(); bean.setUserId("12344"); bean.setCount(11); } Map<String,String> map = bean.getMap(); map.put(operationNumber+"",operationNumber+""); System.out.println("map key = " + operationNumber + " ," + " value = " + operationNumber); RedisUtil.setCache(RedisConstant.testKey, new Gson().toJson(bean)); } }
Action:
public class Action { public Bean getAndUpdateBeanFromCache(){ Bean bean = new Bean(); String key = RedisConstant.testKey; String value = RedisUtil.getCache(key); Type type = new TypeToken<Bean>(){}.getType(); bean = new Gson().fromJson(value,type); return bean; } }
MainClass:
public class MainClass { public static void main(String[] args) throws InterruptedException { for(int i = 0;i<100;i++){ Thread t = new Thread(new TaskRunnable(i)); //启动一百个线程测试 t.start(); } } }
出现的问题,启动的一百个线程中并不是没有count都被记录下来,主要原因是因为HashMap这种数据结构在并发的时候存在一定的问题,但是如何解决这个问题,最后采用了Redis Hash Map的数据结构记录了用户的使用,经测试不会出现并发问题。主要原因是Redis是个单线程运行的程序,其中HashMap并不会出现这个并发的问题。
2.曾宪杰 大型网站系统与Java中间件实践
在这个本书中举出一个例子,跟这个很相似,如下:
public class TestClass { private HashMap<String,Integer> map = new HashMap<String,Integer>(); public synchronized void add(String key){ Integer value = map.get(key); if(value==null){ map.put(key, 1); }else{ map.put(key, value+1); } } }
这个方法虽然能够正确的计数,但是在高并发的时候,却十分的影响性能,效率不高。将Map换成ConcurrentHashMap这个结构,代码如下:
public class TestClass { private ConcurrentHashMap<String,Integer> map = new ConcurrentHashMap<String,Integer>(); public void add(String key){ Integer value = map.get(key); if(value==null){ map.put(key, 1); }else{ map.put(key, value+1); } } }
这样的写法显然会造成高并发的线程的问题。
—-路漫漫其修远兮,吾将上下而求索!
相关文章推荐
- RedisMM ---Redis监控管理系统
- redis-cluster研究和使用
- Redis总体介绍
- redis跟 java相关的操作
- redis的一些基本命令
- Redis的安装、使用以及php中扩展redis并实现php操作redis的一个例子
- Redis介绍及常用命令
- redis常用命令
- Redis系列(六)-SortedSets设计技巧
- linux 下安装redis以及php Redis扩展
- redis实战:redis限制某ip的恶意请求
- Redis 安装教程 (Windows 2.6.13 稳定版)
- java存储GBK编码数据到redis
- CentOS Linux下 redis 下载、安装、配置、主从集群配置
- Redis 源码分析系列1-main函数相关调用分析
- Redis常用命令
- 分布式Redis集群解决方案
- 【ci框架】ci框架中中有关redis文件缓存相关的文件
- redis的no-appendfsync-on-rewrite参数
- 【thinkphp3.2.x】thinkphp3.2.x中有关redis缓存相关的文件