异步调用的接口设计

简介: 异步调用的接口设计

何谓异步?

每次调用都创建一个新的线程去执行, 不会等待上一次调用执行完,再执行下一个请求

SpringBoot项目怎么做

  1. 在启动类上添加:@EnableAsync 注解
  2. 项目中添加下面两个类
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import com.imooc.miaoshaproject.util.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
 * 线程池配置
 **/
@Configuration
public class ThreadPoolConfig
{
    // 核心线程池大小
    private int corePoolSize = 50;
    // 最大可创建的线程数
    private int maxPoolSize = 200;
    // 队列最大长度
    private int queueCapacity = 1000;
    // 线程池维护线程所允许的空闲时间
    private int keepAliveSeconds = 300;
    @Bean(name = "threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor()
    {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(maxPoolSize);
        executor.setCorePoolSize(corePoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // 线程池对拒绝任务(无线程可用)的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
    /**
     * 执行周期性或定时任务
     */
    @Bean(name = "scheduledExecutorService")
    protected ScheduledExecutorService scheduledExecutorService()
    {
        return new ScheduledThreadPoolExecutor(corePoolSize,
                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
        {
            @Override
            protected void afterExecute(Runnable r, Throwable t)
            {
                super.afterExecute(r, t);
                Threads.printException(r, t);
            }
        };
    }
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
 * 线程相关工具类.
 *
 */
public class Threads
{
    private static final Logger logger = LoggerFactory.getLogger(Threads.class);
    /**
     * sleep等待,单位为毫秒
     */
    public static void sleep(long milliseconds)
    {
        try
        {
            Thread.sleep(milliseconds);
        }
        catch (InterruptedException e)
        {
            return;
        }
    }
    /**
     * 停止线程池
     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
     * 如果仍人超時,則強制退出.
     * 另对在shutdown时线程本身被调用中断做了处理.
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool)
    {
        if (pool != null && !pool.isShutdown())
        {
            pool.shutdown();
            try
            {
                if (!pool.awaitTermination(120, TimeUnit.SECONDS))
                {
                    pool.shutdownNow();
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS))
                    {
                        logger.info("Pool did not terminate");
                    }
                }
            }
            catch (InterruptedException ie)
            {
                pool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
    
    /**
     * 打印线程异常信息
     */
    public static void printException(Runnable r, Throwable t)
    {
        if (t == null && r instanceof Future<?>)
        {
            try
            {
                Future<?> future = (Future<?>) r;
                if (future.isDone())
                {
                    future.get();
                }
            }
            catch (CancellationException ce)
            {
                t = ce;
            }
            catch (ExecutionException ee)
            {
                t = ee.getCause();
            }
            catch (InterruptedException ie)
            {
                Thread.currentThread().interrupt();
            }
        }
        if (t != null)
        {
            logger.error(t.getMessage(), t);
        }
    }
}
  1. 在需要异步调用的接口上添加@Async(“threadPoolTaskExecutor”)注解即可
@Async("threadPoolTaskExecutor")
    @RequestMapping(value = "/test",method = {RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public void test() {
        System.out.println("===test===");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
目录
相关文章
|
3月前
|
消息中间件 数据库
开发指南062-异步处理接口
后台有些接口耗时非常长,如果采用同步处理机制,前台等待时间过长,这时需要改异步操作
|
5月前
|
缓存 NoSQL Java
接口幂等该如何设计和实现
本文探讨了程序开发中常见的重复操作问题,如多次点击生成多余订单或支付、RPC调用失败后的重试机制滥用及非法重复请求等。通过接口幂等性设计可有效解决这类问题,确保相同请求多次执行结果一致无副作用。文章详细解释了幂等性的概念及其重要性,并提供了具体的设计与实现方法,包括使用唯一标识符、设计幂等操作、事务处理及缓存策略。此外,还讨论了实现幂等性接口所带来的好处,如并发请求处理、失败请求管理及系统集成等,并提出了验证接口幂等性的策略。通过这些技术和方法的应用,可以显著提升系统的稳定性和用户体验。
122 1
|
7月前
|
JSON 程序员 数据格式
程序员必知:同步接口和异步接口
程序员必知:同步接口和异步接口
484 0
|
8月前
|
JavaScript 中间件 API
中间件使用异步函数
【5月更文挑战第16天】中间件使用异步函数
49 4
|
8月前
|
测试技术
封装并集中处理业务逻辑
封装并集中处理业务逻辑
60 1
|
Java 开发者
异步调用|学习笔记
快速学习异步调用
异步调用|学习笔记
|
安全 前端开发 物联网
接口设计篇《怎么设计好的接口?》
这样设计接口【升职加薪】?
426 0
|
SQL 设计模式 消息中间件
接口设计需要考虑的问题
接口设计需要注意的问题
1786 0
|
API
接口设计
接口设计
152 0
|
SQL JavaScript 前端开发
FIBJS模块重构—从回调到协程
来自FIBJS核心贡献者陈垒在 D2 的演讲 “FIBJS模块重构—从回调到协程”。
FIBJS模块重构—从回调到协程