Java并发编程实战笔记(5)-任务执行

转载请注明出处 http://www.paraller.com
原文排版地址 点击跳转-任务执行/)缓存

相关知识点

  • 大多数并发应用,都是经过任务执行来构造的,经过将任务分红小的工做单元,提供一种天然的事务边界来优化错误恢复过程.
  • 任务执行(Task Execution)的重点在于:独立性明确的任务执行策略
  • 无限制建立线程的不足并发

    • 线程的建立须要时间,消耗大量的运算资源
    • 活跃的线程消耗系统资源,特别是内存;可运行的线程数量多于CPU的数量将会形成闲置,占用内存,大量线程还会引发竞争
    • 稳定性:JVM和Thread构造函数指定的栈大小,以及系统对线程的限制都会形成崩溃。
  • future能够设置超时时间。

Note:
32位的机器,限制因素主要是线程栈的地址空间,每一个线程维护两个执行栈,一个用于Java代码,一个用于原生代码,一般JVM会默认建立一个复合栈,大概是0.5兆(经过 -Xss或者Thread构造函数来设置),2的32次方除以栈大小,会将线程限制在几万内。异步

Executor

  • 任务是一组逻辑工做单元 , 而线程则是任务异步执行的机制
  • Executor能支持多种不一样类型的任务执行策略
  • 提供了一种标准的方法将 任务的提交任务的执行 分开,使用Runnable表示任务
  • 提供了对生命周期统计信息收集程序管理性能监控的支持。
  • 基于生产者-消费者模式,提交任务是生产,执行任务的线程至关于消费者
  • 经过不一样的 Executor的实现就能改变程序的行为。
  • Java类库中,任务执行的主要抽象不是 Thread,而是 Executor
interface Executor{
    void execute(Runnable command);
}
class Demo{
    private final Executor exec = Executors.newFixedThreadPool(100);
    
    void test(){
        // 运行
        Runnable task = new Runnable(){
            public void run(){
                //...
            }
        }
        // 提交
        exec.execute(task);
        
    }
}
线程池

经过管理一组工做线程的资源池,可以减小建立和销毁的开销(资源层面),而且不须要等待,提升响应性
Executor静态工厂方法提供如下几种资源池:函数

  • newFixedThreadPool: 固定大小,若是线程异常结束会补充
  • newCachedThreadPool: 可缓存线程池,少了建立,多了回收
  • newSingleThreadExecutor: 单线程,会按照队列中的顺序(可设置)串行执行
  • newScheduledThreadPool: 固定大小,能延迟或者定时执行
Executor生命周期

Executor实现一般建立线程执行,JVM只有在全部的非守护线程结束才能关闭,
类库提供了 基于 Executor的 ExecutorService接口性能

  • shutdown: 不接受新任务,等待开始的任务结束
  • shutdownNow: 尝试取消全部开始的任务,再也不启动还没有开始(多是已接受的新任务)执行的任务。
interface ExecutorService extends Executor{
    void shutdown();
    List<Runnable> shutdownNow();
    boolean isShutdown();
    ...//
}

生命周期三种状态 运行、关闭、已终止优化

  • ExecutorService关闭后,提交新的任务会抛出 RejectExecutionException
  • 全部任务完成会变成已终止状态
  • awaitTermination会等待 Executor到达终止状态,而且会当即调用shutdown方法。
  • ExecutorService全部submit方法,都会返回一个Future
Timer和ScheduledThreadPoolExecutor

Timer负责管理 延迟任务 和 周期任务;缺陷以下:线程

  • 只会建立一个线程,若是任务耗时过长会影响其余任务
  • Timer线程不捕获异常, TimerTask抛出异常整个Timer任务都会取消。

若是要构建本身的调度器,能够使用DelayQueue和ScheduledThreadPoolExecutor组合。code

异构任务
  • 定义: 不一样类型的任务平均分配给每一个消费者。当消费者增长,在分配工做和协同工做的时候会存在考验。
  • 只有大量相互独立 而且 同构的任务并发处理才能最大限度的提高性能
ExecutorCompletionService
  • 一组Future任务,若是须要知道哪些完成了,须要不停的循环每一个Future的Get方法,很是繁琐。
  • CompletionService 将 Executor 和BlockingQueue 功能融合在一块儿
  • 多个 ExecutorCompletionService 能够共享一个 Executor,
class Demo{
    final ExecutorService executor;

    void test(){
        CompletionService cs = new ExecutorCompletionService(executor); 
        
        for(...){
            cs.submit(new Callable(){
                //...
            });
        }

        for(...){
            // 返回的都是已经计算好结果的Callable
            Future<T> future = cs.take();
            future.get();
        }
    }
}
相关文章
相关标签/搜索