第六章 任务执行
6.1 在线程中执行任务
围绕任务执\执行设计应用程序结构 .讲一个复杂的功能分解为多个独立的任务. 并可以并行执行, 在调度和负载均衡过程中实现更高的灵活性.
6.1.1 串行的执行任务
在单个线程中串行的执行各项任务.
6.1.2 显示的创建任务
正常负载情况下, 为每个任务分配一个线程可以提升串行执行能力.
6.1.3 无限制创建线程的不足
- 线程生命周期的开销非常高.
- 资源消耗 . 活跃的线程会消耗系统资源 , 尤其是内存 .
- 可创建的线程数量存在限制.
6.2 Executor框架
任务:一组逻辑工作单元
线程:使任务异步执行的机制
Excutor 的优点 :
- 支持多种不同类型的任务执行策略
- 典型的生产者--消费者模式, 将任务提交和任务执行解耦
- 提供对生命周期的支持
- 统计信息收集, 应用程序管理机制, 性能监视机制
6.2.2 执行策略
- 在什么线程中执行任务
- 按照什么顺序执行(FIFO , LIFO , 优先级)
- 有多少个任务可以并发执行
- 队列中有多少个任务在等待执行
- 需要拒绝任务时如何选择 , 并进行通知
- 执行任务前后应该进行哪些动作
6.2.3 线程池
管理一组同构(多个相同类型的物体参与完成某一件事情)工作线程的资源池
优势 :
- 通过重用现有的线程节省创建线程的开销
- 提前创建线程, 节省等待时间 . 提高响应性
- 通过调整线程池的大小充分合理的利用CPU资源
6.2.4 Excutor 的生命周期
- 异步方式执行任务
ExecutorService :
- 生命周期有3中状态 : 运行 , 关闭 , 已终止.
- 关闭方式
方式一 :shutDown : 执行平缓的关闭过程 : 不再接受新的任务 , 同时等待提交的任务执行完成.
方式二:shutDownNow : 取消所有运行的任务 , 并不再启动尚未执行的任务
- 所有任务完成后 ExecutorService 转入终止状态
6.2.5 延迟任务与周期任务
Timer
- 基于绝对时间的调度机制( ScheduledThreadPoolExecutor 基于相对时间的调度机制)
比如 某个任务延时300S 后执行, 它就会在 当前毫秒数+延时时间 的那个时刻去执行, 通过修改系统的时间就可以影响任务的执行时间
public void schedule(TimerTask task, long delay) { if (delay < 0) throw new IllegalArgumentException("Negative delay."); sched(task, System.currentTimeMillis()+delay, 0); }
- 执行所有的定时任务时只会创建一个线程. 如果某个任务执行时间过长将会破坏其他任务的定时准确性
// 线程队列 private final TaskQueue queue = new TaskQueue(); // 执行队列任务的线程 private final TimerThread thread = new TimerThread(queue);
- Timer的执行任务的线程不会捕获异常, 如果 timerTask 抛出异常, 将会终止 Timer 的线程.(线程泄露)
6.3 并行性
6.3.1 携带任务结果的Callable 与 Future
Callable 类似与Runnable接口, 但是它可以有返回值,并可以抛出异常
Future 异步计算的结果 通过Future的get()获取call() 方法的返回值
6.3.2 CompletionService
- 使用指定的 Execotor 执行计算任务
- 使用 BlockingQueue 保存计算结果.
- 调用 API 获取计算结果时,若任务尚未完成则阻塞
如果文章对您有所帮助,可以点一下推荐