java线程异步方法

news/2024/10/21 13:38:09
异步的八种实现方式:线程异步 Thread/Runnable
Future + Callable
异步框架 CompletableFuture
Spring 注解 @Async
Spring ApplicationEvent 事件
第三方异步框架,比如 Hutool 的 ThreadUtil
Guava 异步
消息队列
1、线程异步public class ThreadTest implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}public static void main(String[] args) {ThreadTest threadTest = new ThreadTest();new Thread(threadTest).start();}}当然,如果每次都创建一个 Thread 线程,频繁的创建、销毁,浪费系统资源,我们可以采用线程池:【Thread】线程池的 7 种创建方式及自定义线程池2、Future 异步public class FutureTest {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(1);Future<String> future = executor.submit(() -> {Thread.sleep(2000);return "this is future execute final result!!!";});//这里需要返回值时会阻塞主线程String result = future.get();System.out.println(result);executor.shutdown();}}Future的不足之处的包括以下几点:无法被动接收异步任务的计算结果:虽然我们可以主动将异步任务提交给线程池中的线程来执行,但是待异步任务执行结束之后,主线程无法得到任务完成与否的通知,它需要通过get方法主动获取任务执行的结果。
Future件彼此孤立:有时某一个耗时很长的异步任务执行结束之后,你想利用它返回的结果再做进一步的运算,该运算也会是一个异步任务,两者之间的关系需要程序开发人员手动进行绑定赋予,Future并不能将其形成一个任务流(pipeline),每一个Future都是彼此之间都是孤立的,所以才有了后面的CompletableFuture,CompletableFuture就可以将多个Future串联起来形成任务流。
Futrue没有很好的错误处理机制:截止目前,如果某个异步任务在执行发的过程中发生了异常,调用者无法被动感知,必须通过捕获get方法的异常才知晓异步任务执行是否出现了错误,从而在做进一步的判断处理
3、CompletableFuture
关于 CompletableFuture 更多详情请看:【异步】Futurn、FutureTask、CompletionService、CompletableFuturepublic static void thenRunAsync() throws ExecutionException, InterruptedException {CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {System.out.println(Thread.currentThread() + " cf1 do something....");return 1;});CompletableFuture<Void> cf2 = cf1.thenRunAsync(() -> {System.out.println(Thread.currentThread() + " cf2 do something...");});//等待任务1执行完成System.out.println("cf1结果->" + cf1.get());//等待任务2执行完成System.out.println("cf2结果->" + cf2.get());
}4、Spring 注解 @Async@Configuration
public class ThreadPoolConfig {@Bean("taskExecutor")public Executor taskExecutor() {//返回可用处理器的Java虚拟机的数量 12int i = Runtime.getRuntime().availableProcessors();System.out.println("系统最大线程数  : " + i);ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//核心线程池大小executor.setCorePoolSize(16);//最大线程数executor.setMaxPoolSize(20);//配置队列容量,默认值为Integer.MAX_VALUEexecutor.setQueueCapacity(99999);//活跃时间executor.setKeepAliveSeconds(60);//线程名字前缀executor.setThreadNamePrefix("asyncServiceExecutor -");//设置此执行程序应该在关闭时阻止的最大秒数,以便在容器的其余部分继续关闭之前等待剩余的任务完成他们的执行executor.setAwaitTerminationSeconds(60);//等待所有的任务结束后再关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);return executor;}}@Service
@EnableAsync
public class AsyncServiceImpl implements AsyncService {@Override@Async("taskExecutor")public String sendSms() {System.out.println(Thread.currentThread().getName());return null;}@Override@Async("taskExecutor")public String sendEmail() {System.out.println(Thread.currentThread().getName());return null;}}在实际项目中, 使用 @Async 调用线程池,推荐等方式是是使用自定义线程池的模式,不推荐直接使用 @Async 直接实现异步5、Spring ApplicationEvent 事件Spring 中使用事件只需要以下的几个步骤:定义事件,继承 ApplicationEvent
定义监听,要么实现 ApplicationListener 接口,要么在方法上添加 @EventListener 注解
定义发布事件接口,调用 ApplicationContext.publishEvent() 或者 ApplicationEventPublisher.publishEvent();
业务调用发布事件
@Getter
@Setter
public class BaseEvent<T> extends ApplicationEvent {private T data;public BaseEvent(Object source) {super(source);}public BaseEvent(Object source, T data) {super(source);this.data = data;}}@Component
public class BaseEventListener implements ApplicationListener<BaseEvent<UserVo>> {@Override@Async("taskExecutor")public void onApplicationEvent(BaseEvent<UserVo> baseEvent) {UserVo eventData = baseEvent.getData();// TODO 业务处理}}@Autowired
private ApplicationContext applicationContext;@GetMapping("/pubEvent")
public void pubEvent() {BaseEvent<UserVo> baseEvent = new BaseEvent<>("event", new UserVo());applicationContext.publishEvent(baseEvent);
}6、Hutool 的 ThreadUtilpublic static void main(String[] args) {for (int i = 0; i < 3; i++) {ThreadUtil.execAsync(() -> {ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();int number = threadLocalRandom.nextInt(20) + 1;System.out.println(number);});log.info("当前第:" + i + "个线程");}log.info("task finish!");
}7、 Guava 异步public static void test() {ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());final ListenableFuture<Integer> listenableFuture = executorService.submit(() -> {log.info("callable execute...");TimeUnit.SECONDS.sleep(1);return 1;});Futures.addCallback(listenableFuture, new FutureCallback<Integer>() {@Overridepublic void onSuccess(@Nullable Integer integer) {System.out.println("Get listenable future's result with callback " + integer);}@Overridepublic void onFailure(Throwable throwable) {throwable.printStackTrace();}}, Executors.newCachedThreadPool());
}8、 消息队列常用的消息队列:RabbitMq、RocketMq

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/74157.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Java 中的数据加密和安全传输_1

在Java中实现数据加密和安全传输涉及几个关键技术:使用加密算法、实施安全的密钥管理、采用安全传输协议。加密算法如AES和RSA用于保护数据的机密性,防止未授权访问。安全的密钥管理确保只有授权用户才能解密数据。而安全传输协议如SSL/TLS保护数据在网络中的传输。其中,安全…

mybatis的一对多,多对一,以及多对多的配置和使用

根据这个应用场景,我们需要获取在查询一个用户信息的时候还要去读取这个用户发布的帖子 现在我们来看一看用户级联文章在JavaBean中的编写方式,这就是一对多在JavaBean中的配置现在我们再来看一看Mybatis的Mapper该如何编写一对多?很简单,就是在resultMap标签中配置<collec…

PbootCMS执行SQL发生错误(DISK I/O ERROR)怎么办

执行SQL发生错误(DISK I/O ERROR)问题描述:PBootCMS网站程序提示“执行 SQL 发生错误!错误:DISK I/O ERROR”。 解决方案:检查磁盘空间:确保服务器磁盘空间充足,没有满。 检查磁盘健康:使用磁盘检测工具检查磁盘健康状况,确保没有坏道。 优化数据库:优化数据库表,修…

K个节点翻转链表

概述 起因:leetcode题目 25. K 个一组翻转链表 问题描述 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。你不能只是单纯的改变节…

PbootCMS登录后无法使用数据备份功能,备份失败或提示错误怎么办

问题描述:登录后无法使用数据备份功能,备份失败或提示错误。 解决方案:检查文件权限:确保备份目录具有可写权限。 检查数据库连接:确保数据库连接配置正确,数据库服务正常运行。 检查PHP错误日志:查看服务器的PHP错误日志,查找可能的错误信息。 清除缓存:清除浏览器缓…

一文彻底弄清Redis的布隆过滤器

布隆过滤器(Bloom Filter)是一种空间效率极高的数据结构,用于快速判断一个元素是否在集合中。它能够节省大量内存,但它有一个特点:可能存在误判,即可能会认为某个元素存在于集合中,但实际上不存在;而对于不存在的元素,它保证一定不会误判。布隆过滤器适合在对存储空间…

PbootCMS登录后无法上传文件怎么办

登录后无法上传文件问题描述:登录后无法上传文件,提示上传失败。 解决方案:检查文件权限:确保上传目录(如upload/)具有可写权限(通常为755或777)。 检查PHP配置:确保PHP的文件上传设置正确,特别是upload_max_filesize和post_max_size。 检查防火墙和安全设置:确保服…

PbootCMS登录页面无法正常加载,显示为空白页或错误信息怎么办

问题描述:登录页面无法正常加载,显示为空白页或错误信息。 解决方案:检查Web服务器配置:确保Web服务器(如Apache、Nginx)配置正确,特别是虚拟主机配置。 检查PHP配置:确保PHP配置正确,特别是php.ini文件中的设置。 检查文件权限:确保PBootCMS相关目录和文件的权限设置…