线程池:异步处理 + 延迟响应

常见的线程池:

ExecutorService executor = Executors.newCachedThreadPool() ;

1、newFixedThreadPool() 创建固定大小的线程池 线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程

2、newCachedThreadPool() 创建一个可缓存的线程池,如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60s不执行任务)的线程,当任务数量增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于系统(JVM)能够创建的最大线程大小

3、newSingleThreadExecutor() 创建一个单线程的线程池。这个线程池只有线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行

4、newScheduledThreadPool() 创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求

5、newSingleThreadScheduledExecutor() 创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求

写一个不太完美的例子:主线程在处理比较慢的业务逻辑时,可用带返回值的submit(Callable)或submit(Runnable, T),也可用不带返回值的submit(Runnable),均可实现异步处理、同步响应(立即跳出主线程,不会造成阻塞延迟)的效果,不过在用带返回值时,必须不在主线程中使用返回值Future的状态(比如其.get()或.isDone()=true方法),否则还是会造成阻塞等待(进而导致前端超时问题,要是跟前端不用交互,则无此问题)。但问题来了,不用异步线程的Future状态(get()或isDone()=true),怎么知道逻辑处理完了呢?这就需要重新开启一个线程去读这个状态值(期间可以把Future对象作为参数传给新线程去监控其isDone()或get()),当然,这个新线程可以是前端请求过来的(如以下的例子),也可以是后端websocket主动请求前端的。还有一种比较好的方案是在主线程中不使用结果值,同样不造成阻塞等待,同样不造成前端请求超时,但在处理逻辑时需要把任务结果Future或业务层面的结果(比如批量场景下的每条数据、或流程场景下的节点状态数据)存到缓存或数据库,同样地前端页面去重新轮训请求获取这些结果已达到得知处理结果的情况。

        比较一下子,第一个方案是用后台开启监控线程(用线程池创建线程)去监控结果状态,这个状态值是存储在jvm内存里的,所以要求状态值里边的数据不是太大,且机器一挂掉或停电,会造成这些所有的内存里的数据都会消失,所以要求任务数据的安全度不是太高(比如一些爬虫任务或定时任务啥的,就算挂掉后重新开启任务可以继续跑),但其优点是不用前后端频繁创建链接,且由于是线程池在维护监控线程,不用频繁创建销毁线程,且不存在存库问题,也省去了连接库的那一套消耗。第二个方案的特点是跟上边对立的,安全级别高(因为有状态持久化),但频繁调度时可能会牺牲点时间性能,但jvm的内存压力不会太大。总之,还是老生常谈的“牺牲时间换取空间性能,牺牲空间换取时间性能”问题。


public class ThreadPoolTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService e = Executors.newFixedThreadPool(5);
        long l = System.currentTimeMillis();
        final Future<Integer> s = e.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println("执行长逻辑线程:" + Thread.currentThread().getName());
                Thread.sleep(5000);
                return 0;
            }
        });
        System.out.println("主线程:" + Thread.currentThread().getName() + "开始任务~结束任务需要毫秒:" + (System.currentTimeMillis() - l));

        e.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                long q = System.currentTimeMillis();
                while (true) {
                    if (s.isDone()) {
                        try {
                            System.out.println("监控状态线程:" + Thread.currentThread().getName() + ",慢逻辑执行完毕结果:" + s.get());
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        } catch (ExecutionException e1) {
                            e1.printStackTrace();
                        }
                        break;
                    }
                }
                System.out.println("监控状态线程:" + Thread.currentThread().getName() + ",耗时毫秒数" + (System.currentTimeMillis() - q));
                return null;
            }
        });
    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
线程池异步任务的安全性是一个重要的考虑因素。在使用线程池进行异步任务处理时,需要注意以下几点以确保任务的安全性: 1. 线程安全性:确保多个线程在同时访问共享资源时不会导致数据竞争或其他并发问题。可以通过使用线程安全的数据结构或加锁机制来实现。 2. 异常处理:在异步任务中,如果出现异常,需要及时捕获和处理,以避免线程池中的其他任务受到影响。可以使用try-catch语句块来捕获异常,并根据具体情况进行处理。 3. 线程间通信:在某些情况下,异步任务之间需要进行通信或协调。可以使用线程间的通信机制,如通过共享变量、信号量、管道等来实现线程间的数据传递和同步。 4. 取消任务:在某些情况下,可能需要取消正在执行的异步任务。可以通过使用Future对象来实现任务的取消操作。 5. 错误处理异步任务中的错误处理非常重要。当任务失败或发生错误时,需要及时记录日志并采取适当的措施来处理错误,以避免系统崩溃或数据丢失。 综上所述,线程池异步任务的安全性取决于多个因素,包括线程安全性、异常处理线程间通信、任务取消和错误处理等。合理地处理这些因素,可以确保异步任务的安全执行。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [线程池异步处理 + 延迟响应](https://blog.csdn.net/u010730870/article/details/103489256)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [线程池 && 异步编排](https://blog.csdn.net/weixin_50999696/article/details/128101097)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值