任务执行
“任务执行”的意义?
- 简化程序的组织结构
- 提供一种自然的事物边界来优化错误恢复过程
- 提供一种自然的并行结构来提升并发性
在线程中执行任务
如何找出清晰的任务边界?
理想情况下,任务并不依赖其它任务的状态、结果和边界效应
串行的执行任务
串行执行的问题?
性能差,在等待IO时,CPU空闲
响应性和吞吐量查
基于 线程串行 的 Web 案例 :
显式的为任务创建线程
基于 线程并行 的 Web 案例 :
有哪些特点?
- 接受用户请求速度加快
- 请求并发执行
- 任务处理代码必须是现行安全的
无限创建线程会有哪些问题?
- 线程生命周期的开销非常高:线程的创建,切换,消耗等
- 资源消耗 :活跃的线程会消耗系统资源 , 尤其是内存 。大量的闲置线程会导致GC频繁。
- 稳定性:可创建的线程数量存在限制.,超出闲置报OOM错误
Executor 框架
和quene对比?
基于quene,但是简化了线程的管理工作,使用上更加灵活
Executor 框架 有哪些优点?
- 任务提交和任务执行解耦,支持各种执行策略(包含了上面的串行和并行)
- 提供对生命周期的支持,统计信息收集, 应用程序管理机制, 性能监视机制
基于 Executor 的 Web 案例 :
执行策略
有哪些执行策略?
- 在什么线程中执行任务
- 按照什么顺序执行(FIFO , LIFO , 优先级)
- 有多少个任务可以并发执行
- 队列中有多少个任务在等待执行
- 需要拒绝任务时如何选择 , 并进行通知
- 执行任务前后应该进行哪些动作
线程池
管理一组同构(多个相同类型的物体参与完成某一件事情)工作线程的资源池
Executor 生命周期
ExecutorService 扩展 Executor 为提供生命中期的管理:运行、关闭、终止
创建后就处于运行状态
关闭方式:
- shutDown : 执行平缓的关闭过程 : 不再接受新的任务 , 同时等待提交的任务执行完成.
shutDownNow : 取消所有运行的任务 , 并不再启动尚未执行的任务
所有任务完成后 ExecutorService 转入终止状态
ThreadPoolExecutor生命周期:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 > * The runState provides the main lifecycle control, taking on values:
> *
> * RUNNING: Accept new tasks and process queued tasks
> * SHUTDOWN: Don't accept new tasks, but process queued tasks
> * STOP: Don't accept new tasks, don't process queued tasks,
> * and interrupt in-progress tasks
> * TIDYING: All tasks have terminated, workerCount is zero,
> * the thread transitioning to state TIDYING
> * will run the terminated() hook method
> * TERMINATED: terminated() has completed
> *
> * The numerical order among these values matters, to allow
> * ordered comparisons. The runState monotonically increases over
> * time, but need not hit each state. The transitions are:
> *
> * RUNNING -> SHUTDOWN
> * On invocation of shutdown(), perhaps implicitly in finalize()
> * (RUNNING or SHUTDOWN) -> STOP
> * On invocation of shutdownNow()
> * SHUTDOWN -> TIDYING
> * When both queue and pool are empty
> * STOP -> TIDYING
> * When pool is empty
> * TIDYING -> TERMINATED
> * When the terminated() hook method has completed
>
延迟性任务和周期任务
Timer 的不足?
- 基于绝对时间的调度机制:通过修改系统的时间就可以影响任务的执行时间
- 执行所有的定时任务时只会创建一个线程. 如果某个任务执行时间过长将会破坏其他任务的定时准确性
- Timer的执行任务的线程不会捕获异常, 如果 timerTask 抛出异常, 将会终止 Timer 的线程.(线程泄露)
ScheduledThreadPoolExecutor 可以很好的代替 Timer
找出可利用的并行性
案例情形:串行地渲染页面元素
问题一:串行没有充分利用CPU,性能较差,大部分时间都用于IO,用户需要等待时间较长。
优化一:将渲染过程分解为两个任务并发执行,因为有返回,可以使用 Callable 和 Future
Future 和 FutureTask 的区别?
Future 表示 任务Runnable 的生命周期
FutureTask 实现了 Future 和 Runable 接口,是一个能管理自身生命周期的可执行任务
问题二:并行的处理下载图片和渲染文本,但是两者耗时不一致,必须在等待所有的图片都下载完后再进行显示。这就是在异构任务并行化的局限性:异构的任务执行时间不一致,并行的结果取决于耗时最长的任务。
线程生命周期:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 > //FutureTask
> /**
> * The run state of this task, initially NEW. The run state
> * transitions to a terminal state only in methods set,
> * setException, and cancel. During completion, state may take on
> * transient values of COMPLETING (while outcome is being set) or
> * INTERRUPTING (only while interrupting the runner to satisfy a
> * cancel(true)). Transitions from these intermediate to final
> * states use cheaper ordered/lazy writes because values are unique
> * and cannot be further modified.
> *
> * Possible state transitions:
> * NEW -> COMPLETING -> NORMAL
> * NEW -> COMPLETING -> EXCEPTIONAL
> * NEW -> CANCELLED
> * NEW -> INTERRUPTING -> INTERRUPTED
> */
> private volatile int state;
> private static final int NEW = 0;
> private static final int COMPLETING = 1;
> private static final int NORMAL = 2;
> private static final int EXCEPTIONAL = 3;
> private static final int CANCELLED = 4;
> private static final int INTERRUPTING = 5;
> private static final int INTERRUPTED = 6;
>
何为异构任务?
结构不同的任务,也可以理解为两个独立的且逻辑不一样的过程。
优化二:并发的处理大量独立且同构的任务
CompletionService 介绍:
- 使用指定的 Execotor 执行计算任务
- 使用 BlockingQueue 保存计算结果
为什么不使用 ExecutorService 结合 Future?
参考https://www.cnblogs.com/hapjin/p/10898451.html
java8 CompletableFuture更牛批:
- 实现了异步回调(取代了Future.get()的阻塞方式)
- 任务执行流程控制(可以灵活的控制任务执行的流程)