并发编程第二部分结构化并发应用程序

并发编程第二部分结构化并发应用程序
以上代码串行执行,但是handleRequest执行很慢,可用以下方案啊,每次请求都创建一个线程,结构上类似于单线程版本,但是每次accept的时候都可以交给线程去处理,然后接受下一个连接
并发编程第二部分结构化并发应用程序
由此我们可以得出小结论

  • 任务处理过程从主线程分离出来 ,主循环能更快等到下一个到来的连接,这样程序完成前面请求后接受新请求,提高响应性
  • 任务并行处理,服务多个请求,例如等待i/o,获取锁,获取资源可用性,提高程序吞吐量
  • 任务处理必须保证线程安全

接下来讲到基于生产者——消费者模式的框架Exexutor,生产者提交任务,消费者执行任务
并发编程第二部分结构化并发应用程序
创建一个线程池,固定长度线程池可以容纳100个线程
并发编程第二部分结构化并发应用程序
为每一个请求创建线程
并发编程第二部分结构化并发应用程序
也可以编写一个单线程执行任务同步执行并返回
并发编程第二部分结构化并发应用程序

线程池
Executor类库提供了几个工厂方法

  • newFixedThreadPool :创建固定长度线程池,提交一个任务创建一个线程,直到最大,如果发生Exception结束了,会创建一个新的线程
  • newCachedThreadPool:创建可缓存线程池,如果池当前规模超过处理需求,回收空闲线程,需求增加,增加新线程
  • newSingleThreadExecutor:单线程Executor,创建的单线程如果Exception结束,会创建另一个线程来代替。确保串行
  • newScheduledThreadPool:创建固定长度线程池,以延迟定时方式执行
  • newFixedThreadPool
  • TaskExecutionWebServer:web使用Executor用execute将任务提交到工作队列,工作线程反复从队列取出任务并执行。

线程池由为每任务分配一个线程百年城基于线程池策略,web服务器不会在高负债情况下失败,可实现调优、管理、监视、记录日志、报错、so on。。。。。。如果不正确关闭Executor JVM无法结束

Executor生命周期管理方法,调用shutdown即可
并发编程第二部分结构化并发应用程序
延迟与周期任务
可以用ScheduledThreadPoolExecutor

future 任务生命周期只进不退
get()方法取决于任务状态 未开始?运行?已完成?如果已完成,任务抛出Exception,未完成get将阻塞到完成
并发编程第二部分结构化并发应用程序
Callable和Future表示这些协同任务的交互,创建Callable下载所有图像,提交到ExecutorService,返回Future描述任务的执行情况。主任务需要的时候会等待future.get执行结果,幸运的话,已经下载好了,或者已经提前在下载中了。
并发编程第二部分结构化并发应用程序
异常包括两一个是中断,一个是遇到一个Exception。

创建一个BlockingQueue保存计算结果,计算结束调用done,提交任务,先包装成QueueingFuture,改写done方法,访日BlockingQueue
并发编程第二部分结构化并发应用程序

使用CompletionService实现页面渲染器,每个图像下载都创建独立任务,线程池执行,串行转并行
并发编程第二部分结构化并发应用程序
多个任务提交到ExecutorService获取结果 InvokeAll方法的参数为一组,返回一组future,执行完毕,中断,超时,InvokeAll将返回。超时后,未完成的被取消
并发编程第二部分结构化并发应用程序
并发编程第二部分结构化并发应用程序
下面代码用了素数生成器
。,执行1s后取消,现实中银行用此策略停止支付

并发编程第二部分结构化并发应用程序

如果生产者速度超越消费者,那么put一直被阻塞,通过中断来取消
并发编程第二部分结构化并发应用程序
线程在阻塞或者进行重要的工作前检查中断状态
并发编程第二部分结构化并发应用程序
启动线程,timedRun执行join方法,检查任务中是否有异常抛出,在调用timedRun线程中再次抛出一场,由于throwAble在两个线程共享,所以被声明为volatile
并发编程第二部分结构化并发应用程序
将任务交给ExecutorService,通过future.get来获取结果,如果抛出一场,则通过future取消
并发编程第二部分结构化并发应用程序
同步读取套接字,传给processBuffer
并发编程第二部分结构化并发应用程序

并发编程第二部分结构化并发应用程序