java并发编程实战 第六章 任务执行

简介:

一、在线程中执行任务

1、串行地执行任务

当服务器正在处理请求时,新的连接必须等待直到请求处理完毕。
如果请求阻塞时间过长,用户将认为服务器不可用。

2、显式地为任务创建线程

通过每个请求创建一个新的线程来提供服务,从而实现高响应性。
需要创建大量线程时:

  • 线程生命周期开销非常高,线程创建、销毁需要代价
  • 资源消耗,活跃的线程消耗系统资源,尤其是内存。如果可运行的线程数量多于可用处理器的数量,那么有些线程将闲置。
    大量闲置线程占用内存,给垃圾回收带来压力,并在竞争cpu资源时产生性能开销。
  • 稳定性。可创建线程数据存在一个限制。受JVM启动参数、Thread构造函数中请求栈大小、底层操作系统对线程的限制等。

在一定范围内,增加线程可以提高系统吞吐率,超过这个范围,在创建更多的线程只会降低程序的执行速度,甚至系统崩溃。

二、Executor框架

Executor提供了一种标准的方法将任务的提交过程与执行过程解耦,并用Runnable来表示任务。

public interface Executor {
    void execute (Runnbale command);
} 

提供了对生命周期的支持,以及统计信息收集、应用程序管理机制和性能监视等机制。
Executor基于生产者-消费者模式,提交任务相当于生产者,执行任务的线程相当于消费者。

1、线程池

管理一组同构工作线程的资源池。比“为每个任务分配一个线程”优势更:

  • 通过重用现有的线程而不是创建新线程,
  • 可以在处理多个请求时分摊创建线程和销毁的开销。不会等待线程创建而延迟任务执行。
  • 创建足够的线程使处理器保持忙绿,防止过多线程相互竞争资源而使应用程序耗尽内存或失败
  • newSingleThreadPool:单线程的Executor,创建单个工作者线程来执行任务,如果这个线程异常结束,会创建另一个线程来替代。

    可以确保任务在队列中串行执行。
  • newFixedThreadPool:创建一个固定大小的线程池,每当提交一个任务时就创建一个线程,直到达到线程池的最大数量。
  • newCachedThreadPool:创建一个可缓存的线程池,如果线程池当前规模超过了处理需求时,将回收空闲线程;当需求增加时,课添加新的线程,线程池规模无限制
  • newScheduledThreadPool:创建一个固定大小的线程池,而且以延迟或定时的方式来执行任务,类似Timer

    public static ExecutorService newFixedThreadPool(int nThreads) {

    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());

    }
    public static ExecutorService newSingleThreadExecutor() {

    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));

    }
    public static ExecutorService newCachedThreadPool() {

        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());

    }

2、Executor的生命周期

ExecutorService接口添加了生命周期管理方法。
ExecutorService的生命周期有三种状态:运行、关闭、已终止。
在初始化创建时处于运行状态。
shutdown方法将执行平缓关闭过程:不再接受新任务,同时等待已久提交的任务执行完成,包括还未开始执行的任务。
shutdownNow方法执行粗暴关闭过程:长手取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务。

3、延迟任务与周期任务

三、找出可以利用的并行性

如果要使用Executor,必须将任务表述为一个Runnable。

1、携带结果的任务Callbale与Future

Executor框架使用Runnable作为其基本任务的表示形式。

Runnable存在问题:虽然run能写入到日志文件或者将结果放入某个共享的数据结构,但不能返回一个值或抛出一个受检查的异常。
许多任务实际上都是存在延迟计算--执行数据库查询、从网络上获取资源或计算某个复杂功能。
对于这种任务,Callable是一种更好的抽象:它认为主入口点将返回一个值,并可能抛出一个异常。

public interface Callable<V> {
    /**
    * Computes a result, or throws an exception if unable to do so.
    *
    * @return computed result
    * @throws Exception if unable to compute a result
    */
    V call() throws Exception;
}

Executor执行任务有4个生命周期阶段:创建、提交、开始、完成。
在Executor框架中,已提交尚未开始的任务可以取消,对于已经开始执行的任务,只有当它们能响应中断时,才能取消。

Future表示一个任务的生命周期,并提供了相应的方法来判断是否已经完成或取消,以及获取任务的结果和取消任务等。

相关文章
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
539 1
|
安全 Java 开发者
告别NullPointerException:Java Optional实战指南
告别NullPointerException:Java Optional实战指南
445 119
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
430 6
|
安全 前端开发 Java
从反射到方法句柄:深入探索Java动态编程的终极解决方案
从反射到方法句柄,Java 动态编程不断演进。方法句柄以强类型、低开销、易优化的特性,解决反射性能差、类型弱、安全性低等问题,结合 `invokedynamic` 成为支撑 Lambda 与动态语言的终极方案。
436 0
|
人工智能 Java API
Java AI智能体实战:使用LangChain4j构建能使用工具的AI助手
随着AI技术的发展,AI智能体(Agent)能够通过使用工具来执行复杂任务,从而大幅扩展其能力边界。本文介绍如何在Java中使用LangChain4j框架构建一个能够使用外部工具的AI智能体。我们将通过一个具体示例——一个能获取天气信息和执行数学计算的AI助手,详细讲解如何定义工具、创建智能体并处理执行流程。本文包含完整的代码示例和架构说明,帮助Java开发者快速上手AI智能体的开发。
3794 8
|
人工智能 Java API
Java与大模型集成实战:构建智能Java应用的新范式
随着大型语言模型(LLM)的API化,将其强大的自然语言处理能力集成到现有Java应用中已成为提升应用智能水平的关键路径。本文旨在为Java开发者提供一份实用的集成指南。我们将深入探讨如何使用Spring Boot 3框架,通过HTTP客户端与OpenAI GPT(或兼容API)进行高效、安全的交互。内容涵盖项目依赖配置、异步非阻塞的API调用、请求与响应的结构化处理、异常管理以及一些面向生产环境的最佳实践,并附带完整的代码示例,助您快速将AI能力融入Java生态。
1720 12
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
1560 2