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

java 异步

一个CPU核心在同一时刻只能运行一个线程。这是因为每个核心有一套寄存器和执行单元,只能处理一个任务。

一.小测试


/*** 测试异步*/
public class TestThread {public static class AsyncThread extends Thread{@Overridepublic void run(){System.out.println("当前线程名称:" + this.getName() + "," +" 执行线程名称:" + Thread.currentThread().getName() + "-hello");}}public static void main(String[] args) {AsyncThread asyncThread = new AsyncThread();asyncThread.start();AsyncThread asyncThread2 = new AsyncThread();asyncThread2.start();}
}

执行main后得到

        当前线程名称:Thread-1, 执行线程名称:Thread-1-hello
        当前线程名称:Thread-0, 执行线程名称:Thread-0-hello

二.线程池

 private ExecutorService executor = Executors.newCachedThreadPool();public void Func (){executor.submit(new Runnable() {@Overridepublic void run() {try {Thread.sleep(1000);System.out.println("睡一秒");System.out.println("执行线程名称:" + Thread.currentThread().getName() + "-hello");} catch (InterruptedException e) {throw new RuntimeException(e);}}});}/*** 关闭线程池*/public void shutdown(){executor.shutdown();}public static void main(String[] args) {TestThread testThread = new TestThread();testThread.Func();testThread.Func();testThread.Func();testThread.shutdown();}

执行main后得到

        睡一秒
        睡一秒
        睡一秒
        执行线程名称:pool-1-thread-3-hello
        执行线程名称:pool-1-thread-1-hello
        执行线程名称:pool-1-thread-2-hello

增添了shutdown()方法,用于关闭线程池。 

三.Future 获取结果异步

import java.util.concurrent.*;/*** future 异步*/
public class FutureTest {public static void main(String[] args) throws Exception {FutureTest futureTest = new FutureTest();futureTest.futureTest();}public void futureTest() throws Exception{ExecutorService executor = Executors.newFixedThreadPool(1);Future<Integer> future = executor.submit(()->{System.out.println("futureTest");Thread.sleep(5000);return 3;});// 方案1:立即获取结果,阻塞主线程// 方案2:设定超时时间获取结果// 方案3:不获取结果,让任务异步执行System.out.println("main函数执行结束: ");}
}
  • 创建了一个固定大小为 1 的线程池。
  • 往线程池提交了一个会返回整数结果的异步任务
  • 调用System.in.read()让主线程阻塞,防止程序退出。 

3.1 方案1:立即获取结果,阻塞主线程

        try {
            Integer integer = future.get();
            System.out.println("integer = " + integer);
        }catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }finally {
            executor.shutdown();
        }

执行main后得到

        futureTest
        integer = 3
        main函数执行结束:

3.2 方案2:设定超时时间获取结果

        try {
            Integer result = future.get(3, TimeUnit.SECONDS);
            System.out.println("任务结果: " + result);
        } catch (TimeoutException e) {
            System.err.println("任务执行超时");
            future.cancel(true);
        } catch (InterruptedException | ExecutionException e) {
            System.err.println("任务执行异常: " + e.getMessage());
            Thread.currentThread().interrupt();
        } finally {
            executor.shutdown();
        }

执行main后得到

        futureTest
        任务执行超时
        main函数执行结束:

3.3 方案3:不获取结果,让任务异步执行

        executor.shutdown();
        if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
            executor.shutdownNow();
        }

执行main后得到

        futureTest
        main函数执行结束:

 把线程池的关闭操作放在finally块中执行,确保资源能够被正确释放

  • 方案 1:直接调用future.get()获取结果,同时处理可能出现的异常。
  • 方案 2:使用带超时时间的future.get(timeout, unit)方法获取结果,防止长时间阻塞。
  • 方案 3:让任务完全异步执行,通过awaitTermination等待所有任务完成后再关闭线程池。

四.CompletableFuture 异步非阻塞

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;/*** CompletableFuture 异步非阻塞*/
public class CompletableFutureExample {public static void main(String[] args) {int number = 10;CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> factorial(number));try {// 方法1:使用 get() 阻塞(不推荐单独使用)
//             long result = future.get();long result = future.get(5, TimeUnit.MINUTES);System.out.println("Result: " + result);// 方法3:非阻塞方式 - 计算完成时自动触发回调future.thenAccept(res ->System.out.println("异步计算完成,结果: " + res));// 方法4:异常处理future.exceptionally(ex -> {System.err.println("计算过程中发生异常: " + ex.getMessage());return -1L;});} catch (InterruptedException e) {Thread.currentThread().interrupt();System.err.println("线程被中断: " + e.getMessage());} catch (ExecutionException e) {System.err.println("计算异常: " + e.getCause());} catch (TimeoutException e) {System.err.println("计算超时,取消任务");future.cancel(true);}}private static long factorial(int n) {long result = 1;for (int i = 1; i <= n; i++) {result += i;}return result;}}

五.SpringBoot配置异步池

package com.atproject.common.utils;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.ControllerAdvice;
import java.util.concurrent.ThreadPoolExecutor;/*** 线程池配置*/
@ControllerAdvice
@Slf4j
public class ThreadPoolConfiguration {/*** 线程池配置* @return*/@Primary@Bean(name = "threadPoolTaskExecutor", destroyMethod = "shutdown")public ThreadPoolTaskExecutor threadPoolTaskExecutor(){ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(20);executor.setQueueCapacity(200);executor.setKeepAliveSeconds(300);executor.setThreadNamePrefix("custom-executor-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.initialize();return executor;}
}

5.1 方法上使用注解

package com.atproject.threadPool;import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.CompletableFuture;@RestController
@Tag(name = "测试异步", description = "测试异步", extensions = {@Extension(properties = {@ExtensionProperty(name = "x-order", value = "400", parseValue = true)})
})
@RequestMapping("threadPool")
public class ThreadPoolController {/*** 调用异步接口* @return 结果*/@Operation(summary = "调用异步接口", extensions = {@Extension(properties = {@ExtensionProperty(name = "x-order", value = "1", parseValue = true)})})@GetMapping("invokingFunction")@Async("threadPoolTaskExecutor")public CompletableFuture<Boolean> execute(Integer num) {System.out.println("线程:" + Thread.currentThread().getName() + " , 任务:" + num);return CompletableFuture.completedFuture(true);}
}
http://www.xdnf.cn/news/12438.html

相关文章:

  • 2025-适用于Windows11Version 24H2的05累积更新,适合基于x64的系统(KB5058411) 安装错误-0x800f0831
  • 第四章 信息系统管理-4.1 管理方法
  • 正式上线!在 Sui 主网上使用 Nautilus 构建防篡改预言机
  • MCP是什么
  • STM32实战:数字音频播放器开发指南
  • DFT测试之TAP/SIB/TDR
  • 29.【新型数据架构】-边缘计算数据架构
  • Linux top 命令 的使用总结
  • Leetcode 1645. Hopper 公司查询 II
  • python字符串方法
  • NY118NY120美光固态闪存NY124NY129
  • 掌握子网划分:优化IP分配与管理
  • Java建造者模式(Builder Pattern)详解与实践
  • 【PhysUnits】16.1 完善Var 结构体及其运算(variable.rs)
  • Lrc歌词分析
  • 〈软件安装管家软件目录〉▷Windows系统版
  • JAVA理论-JAVA基础知识
  • 结构体和指针1
  • 一文学会《使用Auto CAD2020绘制Allegro PCB板框》
  • 配置URDF模型,调整模型中部件的形状/尺寸,以及在ROS2的Rviz2中进行可视化。
  • 智能化弱电工程项目管理培训
  • 【iSAQB软件架构】构建块、接口
  • 【python深度学习】Day 46 通道注意力(SE注意力)
  • ardupilot 开发环境eclipse 中import 缺少C++
  • 如何使用Webhook触发器,在 ONLYOFFICE 协作空间构建智能工作流
  • Python60日基础学习打卡Day45
  • stm32_DMA
  • 芋道源码 - 配置静态资源匿名访问(图片访问)
  • 分析vban的utlis中的helper方法(2)——树形数组
  • 5.4.3树和森林的遍历