Map在多线程中使用
来源:互联网 发布:淘宝上怎么搜dj香烟 编辑:程序博客网 时间:2024/05/18 13:07
背景:
在实际操作中经常会遇到一种场景,我们需要用一个成员属性Map来保存信息,这时我们可能起两个线程甚至更多,一个线程用来给Map装值,另外一个线程用来每隔一段时间就去Map那取值并清空Map。
实现:
根据上面场景需求,很简单,刷刷刷...,代码写好了,main thread用来给Map装东西,TimeTask thread用来取Map里面的东西
public class AsyMap {private static Map<Integer, String> map = new HashMap<Integer, String>();public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName());//启动时间操作类,每隔一段时间取值new Timer().schedule(new MyTask(), 500, 500);int i = 1;while(true){map.put(i, "content msg" + i);i++;Thread.sleep(200);}}static class MyTask extends TimerTask{@Overridepublic void run() {if (map.size() > 0) {Set<Entry<Integer, String>> entrySet = map.entrySet();for (Entry<Integer, String> entry : entrySet) {System.out.println(entry.getValue());}map.clear();}}}}但是运行之后问题就来了。
原因是多线程的异步,但task在遍历Map取值是,Main thread 也还在往Map中装,这是Map不能容忍的,于是就罢工了。哦原来是异步引起的原因,好竟然HashMap异步不安全,那我用Hashtable,给它加锁总可以了吧!好一通改后代码成这样了
public class AsyTable {private static Map<Integer, String> table = new Hashtable<Integer, String>();public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName());new Timer().schedule(new MyTask(), 500, 500);int i = 1;while(true){table.put(i, "content msg" + i);i++;Thread.sleep(200);}}static class MyTask extends TimerTask{@Overridepublic void run() {if (table.size() > 0) {Set<Entry<Integer, String>> entrySet = table.entrySet();for (Entry<Integer, String> entry : entrySet) {System.out.println(entry.getValue());}table.clear();}}}}
再重新运行,但不幸的是同样的问题再次爆出,这下不好玩了,再滤滤吧!翻翻API,原来Hashtable是给每个public方法加上同步锁当执行到table.entrySet()时它获得了锁,执行到foreach遍历时已经不是调用table的方法了,已经释放了锁,所以也是不行的。既然如此那我就锁对象,在每次从Map中获取值的时候就将它锁住,等到遍历完成后再讲锁释放。优化后代码如下:
public class AsyTable {private static Map<Integer, String> table = new Hashtable<Integer, String>();public static void main(String[] args) throws InterruptedException {System.out.println(Thread.currentThread().getName());new Timer().schedule(new MyTask(), 500, 500);int i = 1;while(true){table.put(i, "content msg" + i);i++;Thread.sleep(200);}}static class MyTask extends TimerTask{@Overridepublic void run() {if (table.size() > 0) {synchronized (table) {Set<Entry<Integer, String>> entrySet = table.entrySet();for (Entry<Integer, String> entry : entrySet) {System.out.println(entry.getValue());}table.clear();}}}}}
运行一下,project run perfestly.
总结:
项目中使用异步往往能提高项目运行效率,但有时候为了数据不被脏读取,则需要给对象加锁。
阅读全文
2 0
- Map在多线程中使用
- 在IOS中使用多线程
- 队列在多线程中使用
- 在wxPython中使用多线程
- 在struts form中使用Map List
- 在ASP.NET中使用Google Map
- 在flex 中使用Google map地图
- 在emacs中使用google map api?!
- 在Html中,图像使用map标签
- 在Android中使用Google map
- 在Android中使用Google map
- 在Tiled Map中使用碰撞检测
- 在Tiled Map中使用碰撞检测
- 如何在MAP中使用结构体
- 在Tiled Map中使用碰撞检测
- 在python中使用多线程下载网页
- 在Asp.net中使用多线程
- 在多线程中使用 IHTMLDocument2 指针
- SSDT表的遍历(源码)
- 从本质矩阵恢复相机矩阵
- 红黑树优点
- Python 中 with用法及原理
- maven 项目中一个模块的debug调试
- Map在多线程中使用
- linux centos挂载盘
- 关于文件读写缓存的问题(flush的使用场景)
- lnmp开发laravel的nginx配置
- Linux驱动学习笔记----------input输入子系统(基本概念与流程)
- Sql分页查询
- Linux负载监控常用指令
- elastaticsearch 插件的安装
- http转dubbo调用