最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程處理千萬級(jí)數(shù)據(jù)更新操作

 更新時(shí)間:2024年11月22日 10:53:23   作者:瑪奇瑪丶  
這篇文章主要為大家詳細(xì)介紹了Java如何通過多線程處理千萬級(jí)數(shù)據(jù)更新操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

故事背景

之前因?yàn)橛脩粜畔踩押脦讉€(gè)敏感信息用AES加密保存了,應(yīng)業(yè)務(wù)需求,需要通過后臺(tái)userId等信息查詢訂單,所以需要明文保存數(shù)據(jù)。但是目前訂單表已經(jīng)有7000萬+訂單數(shù)據(jù),操作起來比較麻煩,肯定需要分批操作的,否則會(huì)有內(nèi)存溢出等問題。初步想到的解決方案是新建一個(gè)數(shù)據(jù)庫表,保存處理訂單表的id是處理到哪一條數(shù)據(jù),然后用limit查詢一萬條數(shù)據(jù),處理完id+10000。

偽代碼

//查詢id
while(id<maxid){
Integer id = mapper.selectList().get(0);
List list = mapper.selectList(Wrappers.<order>lambdaQuery()
        .gt(order::getId,id)
        .last("limit 10000");
for(){
處理數(shù)據(jù)
update數(shù)據(jù)
}
id = list.get(10000).getId();
updateId();
}

這樣update數(shù)據(jù)處理可能會(huì)比較慢,可以用多線程處理。

方案一

用多線程的話需要考慮一下怎么設(shè)計(jì),首先是想著拿到一萬條數(shù)據(jù)之后,分成10份,給10條線程去處理數(shù)據(jù),但是這樣可能會(huì)因?yàn)榫€程處理太慢,線程任務(wù)隊(duì)列太多導(dǎo)致OOM異常,所以可以等待線程全都執(zhí)行完畢再處理下一批數(shù)據(jù)。那么怎么等待線程執(zhí)行完再處理呢?百度完發(fā)現(xiàn)可以用CountDownLatch實(shí)現(xiàn)~

方案二

如果不想等線程執(zhí)行完再處理,可以轉(zhuǎn)換下思路。把list當(dāng)做消息隊(duì)列,每個(gè)線程獲取1千條數(shù)據(jù),如果隊(duì)列數(shù)據(jù)為空則再查詢后面1萬條數(shù)據(jù)做處理。這里有一個(gè)多線程處理共享隊(duì)列的問題,所以需要在取數(shù)據(jù)的時(shí)候和增刪隊(duì)列數(shù)據(jù)的時(shí)候加鎖。

偽代碼

private static List list;
//線程處理
public void run(){
    List dataList;
    while(true){
        synchronized(xx.class){
            if(list.size() == 0){
                list = getList();
            }
            //再判斷一次,如果為空就是處理完了
            if(orderList == null || orderList.size() == 0) {
                return;
            }
            //取最后1千條
            dataList = new ArrayList<>(list.subList(list.size()-1000,list.size()));
            //減去最后一千條
            list = list.subList(0,list.size()-1000);
        }
        //處理dataList
        for(Order order:dataList){
        ...
        }
    }
}

多線程的坑

多線程一定要注意數(shù)據(jù)的并發(fā)安全問題,比如說用subList的話并不會(huì)復(fù)制一個(gè)新的list出來,只是原有l(wèi)ist的基礎(chǔ)上的一個(gè)視圖,如果原來的list改變,subList得到的list也會(huì)跟著改變,如果想要用subList一定要new一個(gè)List接收。

DEMO

public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    for(int i=0;i<100;i++){
        list.add(i);
    }
    while(list.size() >=10){
        //取最后10條
        List<Integer> dataList = list.subList(list.size()-10,list.size());
        //List<Integer> dataList = list.stream().skip(Math.max(0, list.size() - 10)).collect(Collectors.toList()) ;
        ListThread listThread = new ListThread(dataList);
        listThread.start();
        //去掉最后10條數(shù)據(jù)
        list = list.subList(0,list.size()-10);
    }

    list.add(33333);
}


class ListThread extends Thread{
    private List<Integer> list;

    public ListThread(List list){
        this.list = list;
    }

    public void run(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+"開始打印數(shù)據(jù)======");
        for(int i=0;i<list.size();i++){

            System.out.println(list.get(i));
        }
    }

}

如果sleep5秒模擬隊(duì)列的增刪操作,原來的list已經(jīng)變了,會(huì)影響線程里的list變動(dòng),會(huì)報(bào)錯(cuò)

java.util.ConcurrentModificationException

要解決這個(gè)問題需要用創(chuàng)建一個(gè)新的list,這就不會(huì)受原來的list影響

List<Integer> dataList = new ArrayList<>(list.subList(list.size()-10,list.size()));
//或者使用stream流
List<Integer> dataList = list.stream().skip(Math.max(0, list.size() - 10)).collect(Collectors.toList()) ;

后面還遇到一個(gè)問題,new出來的多線程類無法使用@Autowired注入,解決辦法:

1、將需要的Bean作為線程的的構(gòu)造函數(shù)的參數(shù)傳入

2、使用ApplicationContext.getBean方法來靜態(tài)的獲取Bean(推薦)

總結(jié)

1、使用多線程一定要注意線程安全問題,操作共享變量需要加鎖處理,或者分割獨(dú)立的數(shù)據(jù)給各自的線程處理。如果是簡(jiǎn)單且不追求性能的業(yè)務(wù)還是用單線程比較安全。

2、使用subList要注意返回的是視圖,如果原來的list有變化,需要?jiǎng)?chuàng)建一個(gè)新的list接收,或者用stream流做數(shù)據(jù)分割。

3、查詢+處理數(shù)據(jù)速度大概是1分鐘35萬條,大概是這個(gè)時(shí)間,批量update可能還能優(yōu)化,我用的是mybatis-plus自帶的updateBatchById。

到此這篇關(guān)于Java多線程處理千萬級(jí)數(shù)據(jù)更新操作的文章就介紹到這了,更多相關(guān)Java多線程處理數(shù)據(jù)更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java處理日期的工具類DateUtil

    java處理日期的工具類DateUtil

    這篇文章主要為大家詳細(xì)介紹了java處理日期的工具類DateUtil,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • Java中常見HTTP 400錯(cuò)誤的原因和正確處理方法

    Java中常見HTTP 400錯(cuò)誤的原因和正確處理方法

    HTTP 400 Bad Request是客戶端錯(cuò)誤的一種,表示服務(wù)器無法理解或處理客戶端發(fā)送的請(qǐng)求,錯(cuò)誤原因通常在于客戶端請(qǐng)求中存在語法錯(cuò)誤、格式不正確或參數(shù)不符合預(yù)期,所以本文給大家介紹了Java中常見HTTP 400錯(cuò)誤的原因和正確處理方法,需要的朋友可以參考下
    2025-11-11
  • ruoyi-cloud-plus本地nacos微服務(wù)啟動(dòng)不起來的解決方案

    ruoyi-cloud-plus本地nacos微服務(wù)啟動(dòng)不起來的解決方案

    文章主要介紹了修改數(shù)據(jù)庫信息以及將Nacos配置文件內(nèi)容復(fù)制粘貼到數(shù)據(jù)庫中的過程,強(qiáng)調(diào)了根據(jù)實(shí)際情況進(jìn)行修改的重要性,并鼓勵(lì)大家參考和使用
    2026-01-01
  • Java修改eclipse中web項(xiàng)目的server部署路徑問題

    Java修改eclipse中web項(xiàng)目的server部署路徑問題

    這篇文章主要介紹了Java修改eclipse中web項(xiàng)目的server部署路徑,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • MyBatis的<foreach>以及java代碼的批處理方式

    MyBatis的<foreach>以及java代碼的批處理方式

    這篇文章主要介紹了MyBatis的<foreach>以及java代碼的批處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java使用JDK與Cglib動(dòng)態(tài)代理技術(shù)統(tǒng)一管理日志記錄

    Java使用JDK與Cglib動(dòng)態(tài)代理技術(shù)統(tǒng)一管理日志記錄

    這篇文章主要介紹了Java使用JDK與Cglib動(dòng)態(tài)代理技術(shù)統(tǒng)一管理日志記錄,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • java 后臺(tái)開發(fā)中model與entity(實(shí)體類)的區(qū)別說明

    java 后臺(tái)開發(fā)中model與entity(實(shí)體類)的區(qū)別說明

    這篇文章主要介紹了java 后臺(tái)開發(fā)中model與entity(實(shí)體類)的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • JAVA 多線程編程之CountDownLatch使用詳解

    JAVA 多線程編程之CountDownLatch使用詳解

    當(dāng)多個(gè)線程需要協(xié)調(diào)和同步執(zhí)行任務(wù)時(shí),Java中的CountDownLatch(倒計(jì)時(shí)門閂)是一個(gè)常用的工具類,本文將介紹 CountDownLatch 的基本原理、用法以及示例代碼,需要的朋友可以參考下
    2023-05-05
  • SpringBoot yml配置文件調(diào)用過程解析

    SpringBoot yml配置文件調(diào)用過程解析

    這篇文章主要介紹了SpringBoot yml配置文件調(diào)用過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • spring boot 若依系統(tǒng)整合Ueditor部署時(shí)上傳圖片錯(cuò)誤問題

    spring boot 若依系統(tǒng)整合Ueditor部署時(shí)上傳圖片錯(cuò)誤問題

    這篇文章主要介紹了spring boot 若依系統(tǒng)整合Ueditor部署時(shí)上傳圖片錯(cuò)誤問題,本文給大家分享問題解決方法,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10

最新評(píng)論

山阴县| 加查县| 乌鲁木齐市| 沐川县| 辽中县| 泗洪县| 孟村| 昌黎县| 梁河县| 顺平县| 孝昌县| 宜良县| 迁安市| 通道| 太康县| 太仆寺旗| 凌源市| 稻城县| 奉贤区| 宜宾县| 基隆市| 安义县| 新源县| 东莞市| 藁城市| 雷波县| 边坝县| 剑川县| 丹东市| 大化| 中江县| 洪泽县| 梅州市| 双城市| 社旗县| 获嘉县| 南安市| 涞源县| 都兰县| 年辖:市辖区| 清流县|