《java并发编程实战》笔记(第6章)

大多数并发应用程序都是围绕“任务执行”来构造的 :任务通常是一些抽象的而且离散的工作单元。通过把应用程序的工作分解到多个任务中,可以简化程序的组织结构,提供一种自然的事务边界来优化错误恢复过程,以及提供一种自然的并行工作结构来提升并发性。

 在正常的负载下,服务器应用程序应该同时表现出良好的吞吐量和快速的响应性。应用程序提供商希望程序支持尽可能多的用户,从而降低每个用户的服务成本。

 大多数服务器应用程序都提供了一种自然的任务边界选择方式:以独立的客户请求为边界。这样,既可以实现任务的独立性,又可以实现合理的任务规模。

 在服务器应用程序中,串行处理机制通常都无法提供高吞吐率或快速响应性。
 “为每个任务分配一个线程”存在一些缺陷: 1.线程生命周期的开销非常高;2.资源消耗 ; 3.稳定性。

 Executor接口:
 public interface Executor{
      void execute(Runnable command) ;     //Runnable 表示任务
 }

Executor的实现还提供了对生命周期的支持,以及统计信息收集、应用程序管理机制和性能监视等机制。
Executor基于生产者-消费者模式,提交任务的操作相当于生产者(生成待完成的工作单元),执行任务的线程相当于消费者(执行完这些工作单元)。

* 任务的执行策略 (what where when how)

      1.在什么what线程中执行任务?
      2.任务按照什么what顺序执行(FIFO,LIFO,优先级)?
      3.有多少个(how many)任务能并发执行?
      4.在队列中有多少个(How many)任务在等待执行?
      5.如果系统由于过载而需要拒绝一个人物,那么应该选择哪一个(which)任务?另外,如何(how)通知应用程序有任务被拒绝?
      6.在执行一个任务之前或之后,应该进行哪些(what)动作?


 每当看到下面这种形势的代码时:
                     new Thread(runnable).start()
 并且你希望获得一种更灵活的执行策略时,请考虑使用Executor来代替Thread

线程池中执行任务的优点:可以在处理多个请求时分摊在线程创建和销毁过程中产生的巨大开销; 当请求到达时,工作线程通常已经存在,因此不会由于等待创建线程而延迟任务的执行,从而提高了响应性。通过适当调整线程池的大小,可以创建足够多的线程以便使处理器保持忙碌状态,同时还可以防止过多线程相互竞争资源而使应用程序耗尽内存或失败。

* Executor的生命周期

 为了解决执行服务的生命周期问题,Executor扩展了ExecutorService接口,添加了一些用于生命周期管理的方法(同时还有一个用于任务提交的便利方法)

terminate :结束,终止;结果
boolean isShutdown()
如果此执行程序已关闭,则返回 true。
boolean isTerminated()
如果关闭后所有任务都已完成,则返回 true。
void shutdown()
启动一次顺序关闭,执行以前提交的任务,但不接受新任务。 ListshutdownNow()
试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
boolean awaitTermination(long timeout, TimeUnit unit)
请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。

shutdown方法执行平缓的关闭过程:不再接受新的任务,同时等待已经提交的任务执行完成—包括那些还未开始执行的任务。
shutdownNow方法执行粗暴的关闭过程:尝试取消所有运行的任务,并且不再启动队列中尚未开始执行的任务。

* Timer的缺陷

1.Timer在执行所有定时任务时只会创建一个线程,如果每个任务的执行时间过长,那么将破坏其他TimerTask的定时精确性。
2.如果TimerTask抛出一个未检查的异常,那么Timer将表现出糟糕的行为。Timer线程并不捕获异常,因此当TimerTask抛出未检查的异常时将终止定时线程。这种情况下,Timer也不会恢复线程的执行,而是会错误地认为整个Timer都被取消了。因此,已经被调度但尚未执行的TimerTask将不会被执行,新的任务也不能被调度。(这个问题被称为线程泄露)

* get

V get()
throws InterruptedException,
ExecutionException
如有必要,等待计算完成,然后获取其结果。
返回:
计算的结果
抛出:
CancellationException - 如果计算被取消
ExecutionException - 如果计算抛出异常 (可以通过getCause来获取被封装的最初的异常)
InterruptedException - 如果当前的线程在等待时被中断

如何创建一个Future任务
ExecutorService中所有的submit方法都返回一个Future,从而将一个Runnable或Callable提交给Executor,并得到一个Future用来获得任务的执行结果或者取消任务。还可以显式的为某个指定的Runnable或Callable实例化一个FutureTask。(由于FutureTask实现了Runnable,因此可以将它提交给Executor来执行,或者直接调用它的run方法。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值