• 《Java并发编程实战》第六章 任务运行 读书笔记



    一、 在线程中运行任务


    无限制创建线程的不足
    .线程生命周期的开销很高
    .资源消耗
    .稳定性

    二、Executor框架

    Executor基于生产者-消费者模式,提交任务的操作相当于生产者。运行任务的线程则相当于消费者。

    1. Executors 返回 ExecutorService
    2. ExecutorService方法submit、execute
    3. ExecutorService.submit 返回 Future

    线程池,Executors方法介绍
    方法名 解释
    newFixedThreadPool 将创建一个固定长度的线程池,每当提交一个任务时就创建一个线程,知道达到线程池的最大数量。这时线程池的规模将不再变化(假设某个线程因为发生了未预期的Exception而结束,那么线程池会补充一个新的线程。)
    newCachedThreadPool 将创建一个可缓存的线程池,假设线程池的当前规模超过了处理需求时。那么将回收空暇的线程。而当需求添加时,则能够加入新的线程,线程池的规模不存在不论什么限制。

    newSingleThreadExecutor 将会创建一个单线程的Executor。它创建单个工作者线程来运行任务,假设这个线程异常结束,会创建还有一个线程来替代。newSingleThreadExecutor能确保按照任务在队列中的顺序来串行运行(比如FIFO、LIFO、优先级)
    newScheduledThreadPool 创建了一个固定长度的线程池,并且以延迟或定时的方式来运行任务,类似于Timer。



    Executor的生命周期
    以上四个方法都会返回ExecutorService,ExecutorService的生命周期有3种状态:执行、关闭和已终止。

    方法名 解释
    shutdown 将运行平缓的关闭过程:不再接受新的任务。同一时候等待已经提交的任务运行完毕—包含那些还未開始运行的任务。
    shutdownNow 将运行粗暴的关闭过程:它将尝试取消全部运行中的任务,而且不再启动队列中尚未開始运行的任务。


    Timer类负责管理延迟任务

    三、找出可利用的并行性

    1. 任务拆分到多个子线程处理。
    2. 携带结果的任务Callable与Futrue

    Executor运行任务的4个生命周期:创建。提交。開始。完毕。

    任务的提交者和运行者之间的通讯手段
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Callable<Object> task = new Callable<Object>() {
         public Object call() throws Exception {
              Object result = "...";
              return result;
         }
    };
    Future<Object> future = executor.submit(task);
    future.get();  // 等待至完毕
    
    
    Future<Object> future = executor.submit(task);
    // 等待到任务被运行完毕返回结果
    // 假设任务运行出错,这里会抛ExecutionException
    future.get();
    //等待3秒,超时后会抛TimeoutException
    future.get(3,  TimeUnit.SECONDS);
    
    
    Callable<Object> task = new Callable<Object>() {
         public Object call() throws Exception {
              Object result = …;
              return result;
         }
    };

    有两种任务:
    Runnable
    Callable - 须要返回值的任务


    Task Submitter把任务提交给Executor运行,他们之间须要一种通讯手段,这样的手段的详细实现。通常叫做Future。

    Future通常包含get(堵塞至任务完毕)。 cancel。get(timeout)(等待一段时间)
    等等。Future也用于异步变同步的场景。



    3、4. 在异构任务并行化中存在的局限
    假设一个任务是读取IO资源。能够使用多个线程去同一时候读取。可是效率上限可能出在IO上。即使开启再多线程读取总速度也不可能超出IO读取速度上限。

    开启多个线程本身也会调高编程难度,同一时候开启多个线程也会造成资源消耗。
    多线程提高效率非常多时候并非添加一个线程效率提高一倍,可能提高的效率微乎其微。


    5. Executor与BlockingQueue
    假设想提交一组计算任务,而且希望在计算完毕后获得结果,能够使用BlockingQueue保存每一个任务的Future。


    7. 为任务设置时限
    //等待3秒,超时后会抛TimeoutException
    future.get(3,  TimeUnit.SECONDS);


    8. ExecutorService.invokeAll()
    运行给定的任务,当全部任务完毕时。返回保持任务状态和结果的 Future 列表。返回列表的全部元素的 Future.isDone() 为 true。

    注意,能够正常地或通过抛出异常来终止已完毕 任务。假设正在进行此操作时改动了给定的 collection,则此方法的结果是不确定的。 



    四、资料:

    《温绍锦 - Java并发程序设计教程》
         摘录“任务的提交者和运行者”。“任务的提交者和运行者之间的通讯手段” 

    聊聊并发(三)——JAVA线程池的分析和使用(原理)
    http://www.infoq.com/cn/articles/java-threadPool

    Java(Android)线程池(使用)
    http://www.trinea.cn/android/java-android-thread-pool/

    Java Thread Pool Example using Executors and ThreadPoolExecutor
    http://www.journaldev.com/1069/java-thread-pool-example-using-executors-and-threadpoolexecutor

    工具能够查看线程数
    jconsole.exe

  • 相关阅读:
    07 JavaWeb
    06 XML编程(CRUD)
    05 XML
    04 DOM一窥
    03 Javascript初识
    02 CSS/javaScript
    01 HTML基础
    09_IO流
    08_集合概述
    07_基本数据类型和包装类
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7219555.html
Copyright © 2020-2023  润新知