当前位置: 首页 > article >正文

Java中的异步编程模型

1.什么是异步编程?

异步编程是一种编程模式,允许程序在等待某些操作(例如文件I/O或网络请求)完成时,不必停下来等待,而是继续执行其他任务。当异步操作完成时,回调函数或任务调度器会处理结果,从而提高程序的并发性和响应速度。

2.同步 vs 异步

  • 同步:在调用某个方法时,调用方会一直等待该方法执行完毕,才会继续执行后续的操作。期间,调用方被阻塞。
  • 异步:调用某个方法时,调用方可以立即返回,并在方法执行完毕后,通过回调或事件通知的方式处理结果,调用方不会被阻塞。

3.Java中的异步编程工具

Java从java.util.concurrent包开始支持丰富的并发工具,特别是CompletableFuture类,它是异步编程的核心工具。让我们先看看CompletableFuture的基本使用方法。

CompletableFuture:强大的异步任务管理
CompletableFuture是Java 8引入的类,它允许我们轻松地编写异步代码。它不仅可以创建异步任务,还能链式地处理任务结果。

3.1创建异步任务

我们可以通过runAsync()或supplyAsync()方法来创建异步任务。runAsync()适用于不返回结果的任务,而supplyAsync()适用于返回结果的任务。

import java.util.concurrent.CompletableFuture;

public class AsyncExample {
    public static void main(String[] args) {
        // 创建一个异步任务,模拟计算
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("正在执行异步任务...");
            try {
                Thread.sleep(2000);  // 模拟耗时操作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务完成");
        });

        // 主线程继续执行
        System.out.println("主线程继续执行其他操作...");

        // 等待异步任务完成
        future.join();
    }
}

3.2获取异步任务结果

使用supplyAsync()时,我们可以通过thenApply()方法来处理异步任务的结果。thenApply()接收一个函数,表示任务完成后的处理逻辑。

import java.util.concurrent.CompletableFuture;

public class AsyncResultExample {
    public static void main(String[] args) {
        // 创建一个返回结果的异步任务
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("正在计算...");
            return 10 + 20;
        });

        // 处理结果
        future.thenApply(result -> {
            System.out.println("计算结果: " + result);
            return result * 2;
        }).thenAccept(finalResult -> {
            System.out.println("最终结果: " + finalResult);
        });

        // 主线程继续执行
        System.out.println("主线程继续运行...");
    }
}

3.3链式处理任务

CompletableFuture的一个强大功能是它允许链式地组合多个异步任务。每个任务可以依赖于上一个任务的结果,从而形成复杂的异步流程。

import java.util.concurrent.CompletableFuture;

public class ChainedTasksExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            // 第一个任务
            System.out.println("任务1: 获取用户数据...");
            return "用户数据";
        }).thenApply(userData -> {
            // 第二个任务,依赖第一个任务的结果
            System.out.println("任务2: 处理 " + userData);
            return "处理后的" + userData;
        }).thenAccept(finalResult -> {
            // 第三个任务,最终处理结果
            System.out.println("任务3: 显示结果 " + finalResult);
        });

        System.out.println("主线程继续执行...");
    }
}

3.4处理异常

异步任务中可能会发生异常。CompletableFuture提供了exceptionally()方法来捕获并处理异常,确保程序不会因为某个异步任务的失败而崩溃。

import java.util.concurrent.CompletableFuture;

public class ExceptionHandlingExample {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(() -> {
            // 模拟异常
            if (true) {
                throw new RuntimeException("任务失败了");
            }
            return 42;
        }).exceptionally(ex -> {
            System.out.println("发生异常: " + ex.getMessage());
            return -1;  // 返回默认值
        }).thenAccept(result -> {
            System.out.println("最终结果: " + result);
        });

        System.out.println("主线程继续执行...");
    }
}

4.异步事件驱动模型

除了CompletableFuture,在事件驱动开发中,异步编程也是核心。例如,在处理GUI编程、网络请求、I/O操作时,通常通过异步事件驱动模型来提高系统的响应速度。

在Java中,GUI框架如Swing、JavaFX等,都会使用异步事件模型处理用户输入,避免界面阻塞。

4.1例:JavaFX中的异步事件处理

在JavaFX中,我们可以通过异步任务来避免UI卡顿。例如,当我们需要从网络获取数据时,可以使用异步任务来执行,并在任务完成后更新UI。

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class AsyncJavaFXExample extends Application {

    @Override
    public void start(Stage primaryStage) {
        Label label = new Label("等待中...");
        StackPane root = new StackPane(label);

        Scene scene = new Scene(root, 300, 200);

        primaryStage.setTitle("JavaFX异步任务示例");
        primaryStage.setScene(scene);
        primaryStage.show();

        // 创建异步任务
        Task<String> task = new Task<String>() {
            @Override
            protected String call() throws Exception {
                // 模拟耗时操作
                Thread.sleep(2000);
                return "任务完成";
            }
        };

        // 当任务完成时,更新UI
        task.setOnSucceeded(event -> label.setText(task.getValue()));

        // 启动任务
        new Thread(task).start();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

独步天涯路自远,我心如铁志如磐。


http://www.kler.cn/news/361941.html

相关文章:

  • 数据库集群
  • golang正则表达式的使用及举例
  • 【C++】踏上C++学习之旅(三):“我“ 与 “引用“ 的浪漫邂逅
  • 如何利用CMMI帮助组织消除低价值流程
  • 【Python数据库操作】使用SQLite和MySQL进行数据存储和查询!
  • 小巧设计,强大功能:探索SoC模块的多样化功能
  • LN9361 低噪声电荷泵 DC/DC 转换器
  • 什么是缓存?
  • 群控系统服务端开发模式-业务流程图补充
  • Android使用协程实现自定义Toast
  • 一、python基础
  • IDE使用技巧与插件推荐
  • 如何借助月线和日线图选股?
  • 【Linux】/usr/share目录
  • [手机Linux PostmarketOS]七, Linux使用selenium爬虫
  • 自定义全局过滤器统计接口调用耗时
  • Anaconda 使用时conda出问题
  • 转变软件交付方式:通过统一 API 和测试策略提高质量和速度
  • Idea序列图插件-SequenceDiagram Core
  • FactoryBean接口的原理与使用场景
  • 【uniapp】使用Promise封装request
  • 大厂面试真题-了解云原生吗,简单说一下docker和k8s
  • electron-vite_10electron-updater软件更新
  • 【C语言】原码 反码 补码
  • 【知识科普】websocket深入了解
  • 糖果——差分约束 + 正环判定及其优化(手搓栈 + 标记法)