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

来源:互联网 发布:java jsonarray 类 编辑:程序博客网 时间:2024/05/21 11:36

转载请注明出处 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