本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!
从业到现在,一直是看别人的博客,看别人的文章,一直在学习,总结的只是经验性东西,可以复用的,比较深的见解还从未写出来过。今天清英同学号召大家分享并发经验,抛开大家已经写的东西,看看一个从业四年的人是如何看待这个问题的吧!
一直写java程序,一开始从基础操作写起,再者功能,再者逻辑,现者算法,慢慢接触到大型项目,并发、多线程、IO操作就开始用的多了。
在刚开始,接触到用子线程+handler的方式处理任务,完成后给UI线程提供处理结果,稍后用runonuithead,asynctask比较多,用来处理并发任务,主要是网络数据和大操作数据的处理。
上面说的是前台操作,我们再说说后台操作,比如数据库经常性插入删除数据,为了避免对同一个对象进行操作,实现并发,我们会使用synchronized关键字对方法或者资源加锁,一次只处理一个资源,处理完再交给后者;其他也可以使用lock对象,lock和unlock也比较直观;如果可以预知操作时间,也可以通过sleep来处理;或者wait+notify/notifyall,这些对线程进行早期处理的关键字来做。
总之并发的原则就跟出火车票一样,出一张少一张,刷验证码时,谁先输谁就获得这张票的lock权限就可以拿到票,另一个人只好“望洋兴叹”了!说到这儿,讲一个趣闻,早期银行卡不同步,导致有人卡里有2000块,一个ATM机取完,然后驱车到另一个城市再取,还可以取到。听到这儿,你是不是想实际操作下,当然不幸的是我知道的这个问题,已经在当时马上被解决。
最后像在Android当中,有过这样的场景,后台Service在执行若干条联网线程,此时突然断网,我们需要停止线程的运行。像这样,我们可以使用观察者模式,全局定义一个广播,网络停用会发一个广播给我们,然后在广播中通知Service关闭正在执行的线程。并发因为前台逻辑操作多而产生,因后台资源写入权限唯一而解决。
PS:关于容器,同步与并发的概念同时存在,CopyOnWriteArraySet、ConcurrentMap、ConcurrentHashMap,三者都使用了避免ConcurrentModificationException的技术。另外还有常见的HashTable、Vector和StringBuffer,也是实现类似结构,而避免不同步的现象出现。
其他java新特性:java5中提供了AutomicInteger、volatile来保持资源同步,java7中提供了Semaphore来让多个线程同时访问资源,谁先处理完则结束其他,玩的就是硬件+网络处理速度。
明确并发要解决的问题:同时处理多项任务-比如多线程下载
线程的多寡与内核的多寡有关,内核里有执行多线程的机制,俗称分身术,跟孙悟空多个身体一样;从程序意义上来讲,而并发最重要的就是,最多的把内核的分身用起来,压榨它的“剩余价值”,瞬间感觉自己像“资本家”一样。
比较耗时的操作大概有这么三种:磁盘的IO操作,数据库数据的访问以及网络请求,称为“最耗时三剑客”;上面讲述如何从硬件上提高运算能力,但硬件往往延展性不好,操作的灵活性更重要体现在软件上面,因而服务的性能就显得尤其重要(据小道消息,天猫盒子的主要优势在于软件,最大限度的用最差的硬件配合更好的软件,使用较为低廉的价格在在机顶盒市场占据一席之地-这也是大公司牛的地方),衡量一个服务性能好坏的指标是:TPS-Transactions Per Second,即每秒响应请求的次数。如果线程并发有条不紊,效率自然会很高,但出现阻塞甚至死锁,将大大降低程序的并发能力,因而如何实现多线程、做好线程间数据的共享和竞争成为衡量一个并发工程师能力高下的重要指标。并发主要出现在服务端,而服务端一般采用Java语言,因此可以说Java工程师能力的高下,很重要一点就表现在高效并发上。
线程跟进程相比较更加轻量级,一个进程中有无数个线程,从手机端来说一条zygote进程-》若干条系统进程-》个应用进程,这若干个应用进程里有若干条线程,如果多个应用的线程同时对手机内存或者SD卡中数据做写入操作,很容易会发生阻塞或其他非同步问题,关于如何保证多线程数据共享和竞争有以下几个大的方面,需要先行了解一下:
1、不可变 --即对象不可变,可用多种方式实现,如final或so文件
2、绝对线程安全 --使用synchronized关键字锁住执行的所有方法,如Vector
3、相对线程安全 --某些情况话可以不做保障措施
4、线程兼容--在时间或者顺序上调用有次序
5、线程对立--一个要增加一个要减少,或者一个要关闭一个要重启
并发中一个重要的优化策略是建立缓存,因为我们知道“最耗时三剑客”的机制,那么把相应的数据做一下缓存,如文件读取、网络数据和数据库数据,通常一级缓存指存在应用内存中或者叫网站中间件中,由应用内存或中间件在空闲时对关键数据进行同步,这样可以保证前端数据展示流畅,后端数据无缝对接,形成前端数据使用-中间件缓存读取和操作数据-后端被读取和存入数据的模式。
比较著名的缓存机制,如银行的异地备份机制,阿里的分区域请求机制-主要考虑网络延迟等等,复杂的缓存机制可能要做好多层,而最常用的主要是三层,1内存2硬盘3网络。由于缓存机制的存在,不同地区的银行存款、取款、查询以及图片的上传、浏览、删除,需要做到同步,才能符合用户的操作逻辑,因此从业务层也论证高并发同步的必要性。
了解更多:
读书笔记-并发