并发编程之同步 / 异步 / 回调 / 任务 工作流程分析图解

在现代软件开发中,多线程和异步编程已成为提升应用性能和响应速度的关键技术。Java 提供了强大的并发工具,如Thread、Runnable、Callable和Future,这些工具使开发者能够有效地管理线程和任务。Thread和Runnable允许我们创建和执行线程,而Callable和Future则提供了异步计算结果的机制。这些工具和概念不仅帮助我们解决了多线程环境下的复杂问题,还提供了处理暂时性故障和优化资源访问的策略。对于任何希望深入理解并发编程的 Java 开发者来说,掌握这些基础概念和工具是必不可少的。
1、同步与异步
1.1 同步与异步设计图
同步处理:指向同步处理的节点,包括阻塞当前线程、顺序执行和等待结果。
异步处理:指向异步处理的节点,包括不阻塞当前线程、并行执行和回调结果。
同步处理:
阻塞当前线程:在等待操作完成时,当前线程不能执行其他任务。
顺序执行:任务按照顺序一个接一个地执行。
等待结果:线程等待操作完成并获取结果。
异步处理:
不阻塞当前线程:在等待操作完成时,当前线程可以继续执行其他任务。
并行执行:多个任务可以同时执行,提高效率。
回调结果:操作完成后,通过回调函数或其他机制返回结果。
1.2 同步处理时序图
客户端请求数据:客户端发起一个请求,要求同步 API 提供数据。
同步 API 查询数据库:同步 API 将请求转发到数据库。
数据库返回结果:数据库处理请求并将结果返回给同步 API。
同步 API 返回结果:同步 API 将数据库的结果返回给客户端。
1.3 异步处理时序图
客户端发起异步请求:客户端向异步 API 发起一个请求,要求查询数据,但不会等待响应。
异步 API 查询数据库:异步 API 将查询任务发送到数据库,并立即返回,不会阻塞。
数据库处理完毕:数据库在后台处理查询任务。
调用回调函数:一旦数据库处理完毕,异步 API 调用预先定义的回调函数。
返回结果给客户端:回调函数将结果返回给客户端。
1.3 回调时序图
客户端注册回调并发起异步请求:客户端向异步 API 发起请求,并提供一个回调函数,用于在异步操作完成后接收结果。
异步 API 立即返回:异步 API 接收请求后立即返回,不等待异步操作完成。
客户端继续执行:客户端可以继续执行其他任务,而不必等待异步操作的结果。
异步 API 执行异步操作:异步 API 在后台执行异步操作。
异步操作完成:一旦异步操作完成,异步 API 调用之前注册的回调函数。
回调执行:回调函数被执行,处理异步操作的结果。
返回结果给客户端:回调函数将异步操作的结果返回给客户端。
2、任务执行单元
2.1 Thread 工作模式
创建 Thread 对象:通过
new Thread()或其子类构造函数创建一个新的线程对象。设置 Runnable 任务:为线程对象设置一个实现了
Runnable接口的任务。启动线程:调用线程对象的
start()方法来启动线程。线程状态:线程可以处于以下几种状态之一:
运行中:线程正在执行其
run()方法。阻塞:线程等待监视器锁。
等待:线程等待某个条件或超时。
终止:线程执行完毕或被中断。
执行 run 方法:线程开始执行其
run()方法。调用 Runnable.run:
Thread类的run()方法内部调用Runnable任务的run()方法。执行任务:实际的
Runnable任务开始执行。任务执行完毕:
Runnable任务执行完毕。线程结束:任务执行完毕后,线程结束其生命周期。
等待解锁:如果线程需要访问同步代码块或方法,它可能会因为等待锁而被阻塞。
等待条件:线程可能在
wait()、join()或其他等待条件下等待。
3、任务单元
3.1 Runnable 无返回值
Runnable 接口设计
Runnable 接口是 Java 中的一个功能性接口,用于那些可以被线程执行的任务。它只包含一个方法 run(),该方法不接受参数,也不返回任何值(即返回类型为 void)。
接口定义
使用 Runnable 的步骤
实现 Runnable 接口: 创建一个类实现
Runnable接口,并覆盖run()方法来定义任务的执行逻辑。
创建 Thread 对象: 创建
Thread对象时,将实现了Runnable接口的类的实例作为参数传递给Thread构造函数。
启动线程: 调用
Thread对象的start()方法来启动线程。这将导致在新线程中异步执行run()方法。
3.2 Callable 有返回值
Callable 接口设计
Callable接口是 Java 并发编程中的一部分,它允许任务返回结果和抛出异常。以下是Callable接口的基本设计和用法的说明:
接口定义
Callable<V>:Callable是一个泛型接口,V代表返回值的类型。call():这是一个方法,它不接受任何参数,可以返回任何类型的值(V),并且可以抛出任何类型的异常。
使用 Callable 的步骤
实现 Callable 接口: 创建一个类实现
Callable接口,并覆盖call()方法来定义任务的执行逻辑和返回结果。
创建 FutureTask 对象: 将实现了
Callable接口的类的实例传递给FutureTask构造函数。
启动线程: 调用
Thread对象的start()方法来启动线程。这将导致在新线程中异步执行FutureTask的run()方法,该方法内部会调用Callable的call()方法。
4、异步结果
4.1 Future
提交异步任务:通过
ExecutorService提交一个异步任务。ExecutorService:执行异步任务的服务。
Future 对象:
ExecutorService提交任务后返回一个Future对象,该对象可以用来检查计算是否完成、等待计算完成、取消任务和获取计算结果。检查完成:通过
Future对象的isDone()方法检查异步任务是否已完成。已完成:如果任务已完成,通过
Future对象的get()方法获取结果。获取结果:处理异步任务的结果。
未完成:如果任务未完成,可以选择等待或取消任务。
等待或取消:等待任务完成或取消任务。
等待超时:设置超时时间等待任务完成。
取消任务:尝试取消任务。
处理结果:处理异步任务的结果。
处理超时:处理等待超时的情况。
处理取消:处理任务取消的情况
客户端提交任务:客户端向执行器服务提交一个实现了
Callable接口的异步任务。执行器服务执行任务:执行器服务接收到任务后,开始执行异步任务。
异步任务设置结果:异步任务执行完毕后,将结果设置到与
Future对象关联的内部存储中。客户端获取结果:客户端调用
Future对象的get()方法来获取异步任务的结果。任务已完成:如果异步任务已经完成,
Future对象将返回结果给客户端。任务未完成:如果异步任务还未完成,
Future对象将导致客户端阻塞等待,直到任务完成并返回结果。
Future:这是一个接口,定义了以下方法:
cancel(boolean mayInterruptIfRunning):尝试取消执行任务。isCancelled():检查任务是否已被取消。isDone():检查任务是否已完成。get():获取任务的结果,如果任务尚未完成,则阻塞等待。get(long timeout, TimeUnit unit):在指定的超时时间内获取任务的结果。
4.2 FutureTask
创建 FutureTask 对象:创建一个
FutureTask对象,它封装了一个Callable对象(如果任务有返回值)或Runnable对象(如果任务没有返回值)。提交任务:决定是通过
ExecutorService提交任务还是直接在当前线程执行。执行任务:如果通过
ExecutorService提交,任务将被安排在线程池中的某个线程执行。如果是直接执行,则调用FutureTask的run方法。任务状态:检查任务的执行状态。
完成:如果任务正常完成,则设置任务的结果。
被取消:如果任务在执行前被取消,则标记任务为取消状态。
异常:如果任务执行过程中抛出异常,则设置异常信息。
提供结果给调用者:一旦任务完成(无论是正常完成、被取消还是抛出异常),
FutureTask将能够提供结果给调用get方法的线程。客户端提交任务:客户端向执行器服务提交一个实现了
Callable接口的任务。执行器服务创建 FutureTask:执行器服务接收到任务后,创建一个
FutureTask对象来封装这个任务。执行任务:执行器服务执行
FutureTask的run()方法,这将导致在新线程中异步执行Callable任务的call()方法。执行任务逻辑:
Callable任务执行其逻辑,并可能设置结果或异常。通知完成:如果客户端已经调用了
FutureTask的get()方法并正在等待,FutureTask将通知客户端任务已完成。客户端获取结果:客户端调用
FutureTask的get()方法来获取异步任务的结果。任务已完成:如果任务已完成,
FutureTask返回结果给客户端。任务未完成:如果任务未完成,
FutureTask将导致客户端阻塞等待。
FutureTask:这是一个类,它实现了
Runnable和Future接口。它包含任务的执行结果(result)、任务完成状态(done)和取消状态(cancelled)。Callable:这是一个接口,它允许任务返回结果和抛出异常。
Runnable:这是一个接口,它允许任务被线程执行,但不返回结果和异常。
TimeUnit:这是一个枚举,它定义了时间单位,用于
get方法的超时参数。
版权声明: 本文为 InfoQ 作者【肖哥弹架构】的原创文章。
原文链接:【http://xie.infoq.cn/article/37ec550ec0f3eaa42f689c839】。文章转载请联系作者。









评论