并发编程源码和_第1页
并发编程源码和_第2页
并发编程源码和_第3页
并发编程源码和_第4页
并发编程源码和_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 并发编程高级篇(三) 讲师:白鹤翔课程目录7.x JDK多任务执行框架 8.x Concurrent.util工具类详细讲解和使用9.x (重入锁、读写锁使用)锁的高级深化7.1 Executor框架为了更好的控制多线程,JDK提供了一套线程框架Executor,帮助开发人员有效地进行线程控制。它们都在java.util.concurrent包中,是JDK并发包的核心。其中有一个比较重要的类:Executors,他扮演这线程工厂的角色,我们通过Executors可以创建特定功能的线程池。Executors创建线程池方法:newFixedThreadPool()方法,该方法返回一个固定数量的线

2、程池,该方法的线程数始终不变,当有一个任务提交时,若线程池中空闲,则立即执行,若没有,则会被暂缓在一个任务队列中等待有空闲的线程去执行。newSingleThreadExecutor()方法,创建一个线程的线程池,若空闲则执行,若没有空闲线程则暂缓在任务列队中。newCachedThreadPool()方法,返回一个可根据实际情况调整线程个数的线程池,不限制最大线程数量,若用空闲的线程则执行任务,若无任务则不创建线程。并且每一个空闲线程会在60秒后自动回收。newScheduledThreadPool()方法,该方法返回一个SchededExecutorService对象,但该线程池可以指定线

3、程的数量。7.2 自定义线程池若Executors工厂类无法满足我们的需求,可以自己去创建自定义的线程池,其实Executors工厂类里面的创建线程方法其内部实现均是用了ThreadPoolExecutor这个类,这个类可以自定义线程。构造方法如下: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHan

4、dler handler) .7.3 自定义线程池使用详细这个构造方法对于队列是什么类型的比较关键:在使用有界队列时,若有新的任务需要执行,如果线程池实际线程数小于corePoolSize,则优先创建线程,若大于corePoolSize,则会将任务加入队列,若队列已满,则在总线程数不大于maximumPoolSize的前提下,创建新的线程,若线程数大于maximumPoolSize,则执行拒绝策略。或其他自定义方式。无界的任务队列时:LinkedBlockingQueue。与有界队列相比,除非系统资源耗尽,否则无界的任务队列不存在任务入队失败的情况。当有新任务到来,系统的线程数小于corePo

5、olSize时,则新建线程执行任务。当达到corePoolSize后,就不会继续增加。若后续仍有新的任务加入,而有没有空闲的线程资源,则任务直接进入队列等待。若任务创建和处理的速度差异很大,无界队列会保持快速增长,直到耗尽系统内存。JDK拒绝策略:AbortPolicy:直接抛出异常组织系统正常工作CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。DiscardOldestPolicy:丢弃最老的一个请求,尝试再次提交当前任务。DiscardPolicy:丢弃无法处理的任务,不给予任何处理。如果需要自定义拒绝策略可以实现RejectedExec

6、utionHandler接口。8.1 Concurrent.util常用类CyclicBarrier使用:假设有只有的一个场景:每个线程代表一个跑步运动员,当运动员都准备好后,才一起出发,只要有一个人没有准备好,大家都等待。示例:【com.bjsxt.height.concurrent019 UseCyclicBarrier】CountDownLacth使用:他经常用于监听某些初始化操作,等初始化执行完毕后,通知主线程继续工。【com.bjsxt.height.concurrent019 UseCountDownLatch】注意:CyclicBarrieer和CountDownLacth的区别

7、8.2 Concurrent.util常用类Callable和Future使用:这个例子其实就是我们之前实现的Future模式。jdk给予我们一个实现的封装,使用非常简单。【com.bjsxt.height.concurrent019 UseFuture】Future模式非常适合在处理很耗时很长的业务逻辑时进行使用,可以有效的减小系统的响应时间,提高系统的吞吐量。8.3 Concurrent.util常用类在Semaphore信号量非常适合高并发访问,新系统在上线之前,要对系统的访问量进行评估,当然这个值肯定不是随便拍拍脑袋就能想出来的,是经过以往的经验、数据、历年的访问量,已经推广力度进行一

8、个合理的评估,当然评估标准不能太大也不能太小,太大的话投入的资源达不到实际效果,纯粹浪费资源,太小的话,某个时间点一个高峰值的访问量上来直接可以压垮系统。相关概念:PV(page view) 网站的总访问量,页面浏览量或点击量,用户每刷新一次就会被记录一次。UV(unique Visitor)访问网站的一台电脑客户端为一个访客。一般来讲,时间上以00:00 - 24:00 之内相同ip的客户端只记录一次。QPS (query per second)即每秒查询数,qps很大程度上代表了系统业务上的繁忙程度,每次请求的背后,可能对应着多次磁盘I/O,多次网络请求,多个cpu时间片等。我们通过qps

9、可以非常直观的了解当前系统业务情况,一旦当前qps超过所设定的预警阀值,可以考虑增加机器对集群扩容,以免压力过大导致宕机,可以根据前期的压力测试得到估值,在结合后期综合运维情况,估算出阀值。RT (response time)即请求的响应时间,这个指标非常关键,直接说明前端用户的体验,因此任何系统设计师都想降低rt时间。当然还涉及cpu、内存、网络、磁盘等情况,更细节的问题很多,如select、update、delete/ps等数据库层面的统计。8.3 Concurrent.util常用类容量评估:一般来说通过开发、运维、测试、以及业务等相关人员,综合出系统的一系列阀值,然后我们根据关键阀值如

10、qps、rt等,对系统进行有效的变更。一般来讲,我们进行多轮压力测试以后,可以对系统进行峰值评估,采用所谓的80/20原则,即80%的访问请求将在20%的时间内达到。这样我们可以根据系统对应的PV计算出峰值qps。峰值qps= (总PV 80%)/ (60 60 24 20%)然后在将总的峰值qps除以单台机器所能承受的最高的qps值,就是所需要机器的数量:机器数 = 总的峰值qps / 压测得出的单机极限qps当然不排除系统在上线前进行大型促销活动,或者双十一、双十二热点事件、遭受到DDos攻击等情况,系统的开发和运维人员急需要了解当前系统运行的状态和负载情况,一般都会有后台系统去维护。Se

11、maphore可以控制系统的流量:拿到信号量的线程可以进入,否则就等待。通过acquire()和release()获取和释放访问许可。【com.bjsxt.height.concurrent019 UseSemaphore】9.1 锁在java多线程中,我们知道可以使用synchronized关键字来实现线程间的同步互斥工作,那么其实还有一个更优秀的机制去完成这个“同步互斥”工作,他就是Lock对象,我们主要学习两种锁,重入锁和读写锁。他们具有比synchronized更为强大的功能,并且有嗅探锁定、多路分支等功能。9.2 ReentrantLock(重入锁)重入锁,在需要进行同步的代码部分加

12、上锁定,但不要忘记最后一定要释放锁定,不然会造成锁永远无法释放,其他线程永远进不来的结果。【com.bjsxt.height.lock020 UserReentrantLock】9.3 锁与等待/通知。还记得我们在使用synchronized的时候,如果需要多线程间进行协作工作则需要Object的wait()和notify()、notifyAll()方法进行配合工作。那么同样,我们在使用Lock的时候,可以使用一个新的等待/通知的类,它就是Condition。这个Condition一定是针对具体某一把锁的。也就是在只有锁的基础之上才会产生Condition。9.4 多Condition我们可以

13、通过一个Lock对象产生多个Condition进行多线程间的交互,非常的灵活。可以使得部分需要唤醒的线程唤醒,其他线程则继续等待通知。9.5 Lock/Condition其他方法和用法。公平锁和非公平锁:Lock lock = new ReentrantLock(boolean isFair);lock用法:tryLock():尝试获得锁,获得结果用true/false返回。tryLock():在给定的时间内尝试获得锁,获得结果用true/false返回。isFair():是否是公平锁。isLocked():是否锁定。getHoldCount(): 查询当前线程保持此锁的个数,也就是调用loc

14、k()次数。lockInterruptibly():优先响应中断的锁。getQueueLength():返回正在等待获取此锁定的线程数。getWaitQueueLength():返回等待与锁定相关的给定条件Condition的线程数。hasQueuedThread(Thread thread): 查询指定的线程是否正在等待此锁。hasQueuedThreads():查询是否有线程正在等待此锁。hasWaiters():查询是否有线程正在等待与此锁定有关的condition条件。9.6 ReentrantReadWriteLock(读写锁)读写锁ReentrantReadWriteLock,其核心就是实现读写分离的锁。在高并发访问下,尤其是读多写少的情况下,性能要远高于重入锁。之前学

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论