欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java接口異步調用優(yōu)化技巧詳解

 更新時間:2023年05月06日 11:30:53   作者:浮生夢  
本文詳細介紹了在Java開發(fā)中,如何通過異步調用等技巧來優(yōu)化接口的性能,有效避免阻塞和提高并發(fā)處理能力,提升系統的穩(wěn)定性和響應速度

在日常項目中,我們經常采用多線程異步調用的方式來提高接口的響應時間。

在實際情況下,我們如何通過異步方式優(yōu)化我們的接口呢,有以下幾種常見思路

1,自己new線程或者線程池

如下我們把三個耗時操作交給新的線程或者線程池執(zhí)行。

當請求過來的時候tomcat線程會等待子線程全部執(zhí)行完成,然后匯總結果進行返回。

 /**
     * 這里會阻塞tomcat的線程
     */
    @GetMapping("getAllEgOne")
    public Map<String, Object> getAllEgOne() throws ExecutionException, InterruptedException {
        FutureTask<String> stringFutureTaskOne = new FutureTask<>(asyncService::getOne);
        FutureTask<String> stringFutureTaskTwo = new FutureTask<>(asyncService::getTwo);
        FutureTask<String> stringFutureTaskThree = new FutureTask<>(asyncService::getThree);
        new Thread(stringFutureTaskOne).start();
        new Thread(stringFutureTaskTwo).start();
        new Thread(stringFutureTaskThree).start();
        Map<String, Object> result = new HashMap<>();
        result.put("one", stringFutureTaskOne.get());
        result.put("two", stringFutureTaskTwo.get());
        result.put("three", stringFutureTaskThree.get());
        return result;
    }

2,Sping Mvc

我們返回一個Callable 這時候會開啟一個新的線程不會阻塞tomcat的線程

 /**
     * 這里不會阻塞tomcat的線程
     */
    @GetMapping("getAllEgTwo")
    public Callable<Map<String, Object>> getAllEgTwo() {
        return () -> {
            FutureTask<String> stringFutureTaskOne = new FutureTask<>(asyncService::getOne);
            FutureTask<String> stringFutureTaskTwo = new FutureTask<>(asyncService::getTwo);
            FutureTask<String> stringFutureTaskThree = new FutureTask<>(asyncService::getThree);
            new Thread(stringFutureTaskOne).start();
            new Thread(stringFutureTaskTwo).start();
            new Thread(stringFutureTaskThree).start();
            Map<String, Object> result = new HashMap<>(3);
            result.put("one", stringFutureTaskOne.get());
            result.put("two", stringFutureTaskTwo.get());
            result.put("three", stringFutureTaskThree.get());
            return result;
        };
    }

3,修改單個任務為批量任務

在項目中我們有很多數據庫的查詢,批量查詢要快于單個查詢,中間省了很多io操作。

思考能不能吧單個調用轉換成批量呢,針對并發(fā)比較高的接口。合并多個用戶的調用,轉換成一批進行查詢。

把一個時間段內的請求放進隊列,然后通過定時任務進行批量查詢,然后進行響應分發(fā)。

import com.example.demo.conf.SnowFlake;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
/**
 * @author liwenchao
 */
@RestController
@RequestMapping("async")
@Slf4j
public class AsyncController {
    @Autowired
    private AsyncService asyncService;
    private final SnowFlake worker = new SnowFlake(1, 1, 1);
    private final LinkedBlockingQueue<RequestBody<Long, UserInfo>> queue = new LinkedBlockingQueue<>();
    @PostConstruct
    public void doWork() {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        service.scheduleAtFixedRate(() -> {
            //每次運行的時候 去拿MQ中的數據量
            int size = queue.size();
            if (size == 0) {
                return;
            }
            log.info("批量獲取任務:{}-{}", Thread.currentThread().getName(), size);
            //多次請求收集到一起一塊去批量請求下面的需要的數據
            List<Long> requestBodyList = new ArrayList<>();
            List<RequestBody<Long, UserInfo>> requestBodies = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                RequestBody<Long, UserInfo> requestBody = queue.poll();
                requestBodies.add(requestBody);
                Long requestParam = requestBody.getRequestParam();
                requestBodyList.add(requestParam);
            }
            List<UserInfo> fourBatch;
            try {
                fourBatch = asyncService.getFourBatch(requestBodyList);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (CollectionUtils.isEmpty(fourBatch)) {
                return;
            }
            for (UserInfo x : fourBatch) {
                for (RequestBody<Long, UserInfo> y : requestBodies) {
                    if (x.getId().equals(y.getRequestParam())) {
                        y.getResult().complete(x);
                        break;
                    }
                }
            }
        }, 1000L, 50L, TimeUnit.MILLISECONDS);
    }
    /**
     * ● 插入
     * 1.add(e):當阻塞隊列滿時,再往隊列里add插入元素會拋IllegalStateException:Queue full
     * 2.offer(e):插入方法,成功true失敗返回false
     * 3.put(e):當阻塞隊列滿時,生產者線程繼續(xù)往隊列里添加元素,隊列會一直阻塞生產者線程。直到put數據or響應中斷退出
     * 4.offer(e,time,unit):當阻塞隊列滿的時候,隊列會阻塞生產者線程一定時間,超過限時后生產者線程會退出。
     * <p>
     * ● 移除
     * 1.remove():當隊列為空的時候,再往隊列里remove移除元素會拋NoSuchElementException
     * 2.poll():移除方法,成功返回出隊列的元素,隊列里沒有就返回null。
     * 3.take():當隊列為空消費者線程試圖從隊列里take元素,隊列會一直阻塞消費者線程知道隊列可用
     * 4.poll(time,unit):當隊列為空的時候,會阻塞一段時間超時后消費者線程退出。
     * <p>
     * ● 檢查
     * 1.element():當隊列為空時直接拋出異常
     * 2.peek():當隊列為空時阻塞
     * <p>
     * 這里不會阻塞tomcat的線程
     */
    @GetMapping("getAllEgFour")
    public UserInfo getAllEgFour(Long userId) throws ExecutionException, InterruptedException {
        if (userId == null) {
            userId = worker.nextId();
        }
        log.info("開始獲取數據: {}: {}", Thread.currentThread().getName(), userId);
        RequestBody<Long, UserInfo> objectObjectRequestBody = new RequestBody<>();
        CompletableFuture<UserInfo> completableFuture = new CompletableFuture<>();
        objectObjectRequestBody.setRequestParam(userId);
        objectObjectRequestBody.setResult(completableFuture);
        queue.add(objectObjectRequestBody);
        UserInfo userInfo = completableFuture.get();
        log.info("完成獲取數據: {}: {}", Thread.currentThread().getName(), userInfo);
        return userInfo;
    }
}

到此這篇關于Java接口異步調用優(yōu)化技巧詳解的文章就介紹到這了,更多相關Java接口異步調用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Sentinel的熔斷降級、資源規(guī)則詳解與實例

    Sentinel的熔斷降級、資源規(guī)則詳解與實例

    這篇文章主要介紹了Sentinel的熔斷降級、資源規(guī)則詳解與實例,Sentinel是阿里巴巴開源的一款流量控制和熔斷降級的框架,它主要用于保護分布式系統中的服務穩(wěn)定性,Sentinel通過對服務進行流量控制和熔斷降級,可以有效地保護系統的穩(wěn)定性,需要的朋友可以參考下
    2023-09-09
  • multi-catch和try-catch異常處理知識點詳解

    multi-catch和try-catch異常處理知識點詳解

    在本篇文章里我們給大家分享了一篇關于multi-catch和try-catch異常處理知識點內容,有需要的朋友們可以參考學習下。
    2019-11-11
  • Spring?Lifecycle?和?SmartLifecycle區(qū)別面試精講

    Spring?Lifecycle?和?SmartLifecycle區(qū)別面試精講

    這篇文章主要為大家介紹了Spring?Lifecycle和SmartLifecycle的區(qū)別面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • Java簡單使用redis-zset實現排行榜

    Java簡單使用redis-zset實現排行榜

    這篇文章主要介紹了Java簡單使用redis-zset實現排行榜,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • 淺談java泛型的作用及其基本概念

    淺談java泛型的作用及其基本概念

    下面小編就為大家?guī)硪黄獪\談java泛型的作用及其基本概念。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • SpringBoot利用隨機鹽值實現密碼的加密與驗證

    SpringBoot利用隨機鹽值實現密碼的加密與驗證

    這篇文章主要為大家詳細介紹了SpringBoot如何利用隨機鹽值實現密碼的加密與驗證,文中的示例代碼講解詳細,有需要的小伙伴可以參考下
    2024-02-02
  • 利用Spring IOC技術實現用戶登錄驗證機制

    利用Spring IOC技術實現用戶登錄驗證機制

    這篇文章主要為大家詳細介紹了Spring IOC技術實現用戶登錄驗證機制的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Spring中BeanFactory解析bean詳解

    Spring中BeanFactory解析bean詳解

    本篇文章主要介紹了Spring中BeanFactory解析bean詳解 ,詳細的介紹了使用BeanFactory對bean進行解析的實例,有興趣的可以了解一下。
    2017-04-04
  • Java基礎之淺談hashCode()和equals()

    Java基礎之淺談hashCode()和equals()

    今天給大家?guī)淼氖顷P于Java基礎的相關知識,文章圍繞著hashCode()和equals()展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 深入探究SpringBoot中的Elasticsearch自動配置原理及用法

    深入探究SpringBoot中的Elasticsearch自動配置原理及用法

    SpringBoot中的Elasticsearch自動配置為我們提供了一種快速集成Elasticsearch的方式,使我們可以在SpringBoot應用程序中輕松地使用Elasticsearch,本文將介紹Spring Boot中的Elasticsearch自動配置的作用、原理和使用方法
    2023-07-07

最新評論