精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用雙異步后,如何保證數據一致性?

數據庫 其他數據庫
AbstractQueuedSynchronizer簡稱AQS,它是一個同步框架,它提供通用機制來原子性管理同步狀態、阻塞和喚醒線程,以及 維護被阻塞線程的隊列。基于 AQS 實現的同步器包括:ReentrantLock、Semaphore、ReentrantReadWriteLock、 CountDownLatch 和 FutureTask。

一、前情提要

在上一篇文章中,我們使用雙異步后,從 191s 優化到 2s,有個小伙伴在評論區問我,如何保證插入后數據的一致性呢?

很簡單,通過對比Excel文件行數和入庫數量是否相等即可。

那么,如何獲取異步線程的返回值呢?

二、通過Future獲取異步返回值

我們可以通過給異步方法添加Future返回值的方式獲取結果。

FutureTask 除了實現 Future 接口外,還實現了 Runnable 接口。因此,FutureTask 可以交給 Executor 執行,也可以由調用線程直接執行FutureTask.run()。

1、FutureTask 是基于 AbstractQueuedSynchronizer實現的

AbstractQueuedSynchronizer簡稱AQS,它是一個同步框架,它提供通用機制來原子性管理同步狀態、阻塞和喚醒線程,以及 維護被阻塞線程的隊列。基于 AQS 實現的同步器包括:ReentrantLock、Semaphore、ReentrantReadWriteLock、 CountDownLatch 和 FutureTask。

基于 AQS實現的同步器包含兩種操作:

  • acquire,阻塞調用線程,直到AQS的狀態允許這個線程繼續執行,在FutureTask中,get()就是這個方法;
  • release,改變AQS的狀態,使state變為非阻塞狀態,在FutureTask中,可以通過run()和cancel()實現。

2、FutureTask執行流程

執行@Async異步方法。

建立新線程async-executor-X,執行Runnable的run()方法,(FutureTask實現RunnableFuture,RunnableFuture實現Runnable)。

判斷狀態state。

  • 如果未新建或者不處于AQS,直接返回。
  • 否則進入COMPLETING狀態,執行異步線程代碼。

如果執行cancel()方法改變AQS的狀態時,會喚醒AQS等待隊列中的第一個線程線程async-executor-1。

線程async-executor-1被喚醒后

  • 將自己從AQS隊列中移除。
  • 然后喚醒next線程async-executor-2。
  • 改變線程async-executor-1的state。
  • 等待get()線程取值。

next等待線程被喚醒后,循環線程async-executor-1的步驟。

  • 被喚醒。
  • 從AQS隊列中移除。
  • 喚醒next線程。
  • 改變異步線程狀態。

新建線程async-executor-N,監聽異步方法的state。

  • 如果處于EXCEPTIONAL以上狀態,拋出異常。
  • 如果處于COMPLETING狀態,加入AQS隊列等待。
  • 如果處于NORMAL狀態,返回結果。

3、get()方法執行流程

get()方法通過判斷狀態state觀測異步線程是否已結束,如果結束直接將結果返回,否則會將等待節點扔進等待隊列自旋,阻塞住線程。

自旋直至異步線程執行完畢,獲取另一邊的線程計算出結果或取消后,將等待隊列里的所有節點依次喚醒并移除隊列。

如果state小于等于COMPLETING,表示任務還在執行中。

  • 計算超時時間。
  • 如果超時,則從等待隊列中移除等待節點WaitNode,返回當前狀態state。
  • 阻塞隊列nanos毫秒。
  • 如果已有等待節點WaitNode,將線程置空。
  • 返回當前狀態。
  • 如果線程被中斷,從等待隊列中移除等待節點WaitNode,拋出中斷異常。
  • 如果state大于COMPLETING。
  • 如果任務正在執行,讓出時間片。
  • 如果還未構造等待節點,則new一個新的等待節點。
  • 如果未入隊列,CAS嘗試入隊。
  • 如果有超時時間參數。
  • 否則阻塞隊列。

如果state大于COMPLETING。

  • 如果執行完畢,返回結果。
  • 如果大于等于取消狀態,則拋出異常。

很多小朋友對讀源碼,嗤之以鼻,工作3年、5年,還是沒認真讀過任何源碼,覺得讀了也沒啥用,或者讀了也看不懂~

其實,只要把源碼的執行流程通過畫圖的形式呈現出來,你就會幡然醒悟,原來是這樣的~

簡而言之:

  • 如果異步線程還沒執行完,則進入CAS自旋。
  • 其它線程獲取結果或取消后,重新喚醒CAS隊列中等待的線程。
  • 再通過get()判斷狀態state;。
  • 直至返回結果或(取消、超時、異常)為止。

三、FutureTask源碼具體分析

1、FutureTask源碼

通過定義整形狀態值,判斷state大小,這個思想很有意思,值得學習。

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}
public class FutureTask<V> implements RunnableFuture<V> {

 // 最初始的狀態是new 新建狀態
 private volatile int state;
    private static final int NEW          = 0; // 新建狀態
    private static final int COMPLETING   = 1; // 完成中
    private static final int NORMAL       = 2; // 正常執行完
    private static final int EXCEPTIONAL  = 3; // 異常
    private static final int CANCELLED    = 4; // 取消
    private static final int INTERRUPTING = 5; // 正在中斷
    private static final int INTERRUPTED  = 6; // 已中斷

 public V get() throws InterruptedException, ExecutionException {
     int s = state;
     // 任務還在執行中
     if (s <= COMPLETING)
         s = awaitDone(false, 0L);
     return report(s);
 }
 
 private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
         // 線程被中斷,從等待隊列中移除等待節點WaitNode,拋出中斷異常
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }

            int s = state;
            // 任務已執行完畢或取消
            if (s > COMPLETING) {
             // 如果已有等待節點WaitNode,將線程置空
                if (q != null)
                    q.thread = null;
                return s;
            }
            // 任務正在執行,讓出時間片
            else if (s == COMPLETING) // cannot time out yet
                Thread.yield();
            // 還未構造等待節點,則new一個新的等待節點
            else if (q == null)
                q = new WaitNode();
            // 未入隊列,CAS嘗試入隊
            else if (!queued)
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                     q.next = waiters, q);
            // 如果有超時時間參數
            else if (timed) {
             // 計算超時時間
                nanos = deadline - System.nanoTime();
                // 如果超時,則從等待隊列中移除等待節點WaitNode,返回當前狀態state
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                // 阻塞隊列nanos毫秒
                LockSupport.parkNanos(this, nanos);
            }
            else
             // 阻塞隊列
                LockSupport.park(this);
        }
    }
    
 private V report(int s) throws ExecutionException {
  // 獲取outcome中記錄的返回結果
        Object x = outcome;
        // 如果執行完畢,返回結果
        if (s == NORMAL)
            return (V)x;
            // 如果大于等于取消狀態,則拋出異常
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }
}

2、將異步方法的返回值改為Future<Integer>,將返回值放到new AsyncResult<>();中

@Async("async-executor")
public void readXls(String filePath, String filename) {
    try {
     // 此代碼為簡化關鍵性代碼
        List<Future<Integer>> futureList = new ArrayList<>();
        for (int time = 0; time < times; time++) {
            Future<Integer> sumFuture = readExcelDataAsyncFutureService.readXlsCacheAsync();
            futureList.add(sumFuture);
        }
    }catch (Exception e){
        logger.error("readXlsCacheAsync---插入數據異常:",e);
    }
}
@Async("async-executor")
public Future<Integer> readXlsCacheAsync() {
    try {
        // 此代碼為簡化關鍵性代碼
        return new AsyncResult<>(sum);
    }catch (Exception e){
        return new AsyncResult<>(0);
    }
}

3、通過Future<Integer>.get()獲取返回值:

public static boolean getFutureResult(List<Future<Integer>> futureList, int excelRow){
    int[] futureSumArr = new int[futureList.size()];
    for (int i = 0;i<futureList.size();i++) {
        try {
            Future<Integer> future = futureList.get(i);
            while (true) {
                if (future.isDone() && !future.isCancelled()) {
                    Integer futureSum = future.get();
                    logger.info("獲取Future返回值成功"+"----Future:" + future
                            + ",Result:" + futureSum);
                    futureSumArr[i] += futureSum;
                    break;
                } else {
                    logger.info("Future正在執行---獲取Future返回值中---等待3秒");
                    Thread.sleep(3000);
                }
            }
        } catch (Exception e) {
            logger.error("獲取Future返回值異常: ", e);
        }
    }
    
    boolean insertFlag = getInsertSum(futureSumArr, excelRow);
    logger.info("獲取所有異步線程Future的返回值成功,Excel插入結果="+insertFlag);
    return insertFlag;
}

4、這里也可以通過新線程+Future獲取Future返回值

不過感覺多此一舉了,就當練習Future異步取返回值了~

public static Future<Boolean> getFutureResultThreadFuture(List<Future<Integer>> futureList, int excelRow) {
    ExecutorService service = Executors.newSingleThreadExecutor();
    final boolean[] insertFlag = {false};
    service.execute(new Runnable() {
        public void run() {
            try {
                insertFlag[0] = getFutureResult(futureList, excelRow);
            } catch (Exception e) {
                logger.error("新線程+Future獲取Future返回值異常: ", e);
                insertFlag[0] = false;
            }
        }
    });
    service.shutdown();
    return new AsyncResult<>(insertFlag[0]);
}

獲取異步線程結果后,我們可以通過添加事務的方式,實現Excel入庫操作的數據一致性。

但Future會造成主線程的阻塞,這個就很不友好了,有沒有更優解呢?

在BUG中磨礪,在優化中成長,我們下期見~


責任編輯:姜華 來源: 哪吒編程
相關推薦

2024-12-26 15:01:29

2025-03-27 08:20:54

2023-09-07 08:11:24

Redis管道機制

2024-08-20 16:13:52

2023-05-26 07:34:50

RedisMySQL緩存

2022-12-05 08:24:32

mongodb數據庫數據

2021-12-14 07:15:57

MySQLRedis數據

2024-07-04 12:36:50

2023-09-15 14:24:54

ByteHouseClickHouse開源

2021-12-05 21:06:27

軟件

2022-08-23 07:46:45

數據一致性數據庫

2022-03-31 08:21:14

數據庫緩存雙寫數據一致性

2022-10-19 12:22:53

并發扣款一致性

2023-12-11 12:27:31

并發Zookeeper數據

2019-08-30 12:46:10

并發扣款查詢SQL

2022-02-17 21:04:27

數據庫MysqlRedis

2018-08-14 10:39:04

數據錯誤DIX

2020-09-03 09:45:38

緩存數據庫分布式

2025-04-27 08:52:21

Redis數據庫緩存

2021-03-04 06:49:53

RocketMQ事務
點贊
收藏

51CTO技術棧公眾號

国产欧美一区二区三区米奇| sm在线观看| 韩国成人在线视频| 久久久亚洲国产天美传媒修理工| 中文字幕在线永久| 自拍偷自拍亚洲精品被多人伦好爽 | 一级片在线免费观看视频| 欧美理论在线| 亚洲人成在线一二| 亚洲欧洲日韩综合| 992tv国产精品成人影院| 亚洲一区国产视频| 午夜午夜精品一区二区三区文| 国产精选久久久| 老鸭窝亚洲一区二区三区| 美女av一区二区| 国产特黄级aaaaa片免| 国产精品日韩精品在线播放 | 五月丁香综合缴情六月小说| www.视频在线.com| 成人av在线影院| 成人两性免费视频| 国产日韩在线免费观看| 伊人精品成人久久综合软件| 中文字幕精品网| 91av在线免费| 91精品尤物| 在线成人高清不卡| 成人免费视频久久| 19禁羞羞电影院在线观看| 综合久久给合久久狠狠狠97色 | 色婷婷久久99综合精品jk白丝| 成年在线观看视频| 一级日本在线| 国产视频一区二区在线观看| 激情视频一区二区| 国产精品视频第一页| 青青草精品视频| 欧美中文在线免费| 国产精品suv一区二区| 中文字幕免费精品| 久久精品这里热有精品| 免费看一级黄色| 欧美先锋资源| 亚洲一区二区久久久| 亚洲专区区免费| 久久久久久毛片免费看 | 欧美体内she精视频| 欧美日韩在线视频一区二区三区| 福利小视频在线| 亚洲一区二区三区视频在线播放| 超级碰在线观看| aaa大片在线观看| 亚洲欧美一区二区三区孕妇| 中文有码久久| 美女av在线播放| 国产精品久久久久久妇女6080| 色吧亚洲视频| 日本免费在线视频| 亚洲欧美怡红院| 青青草免费在线视频观看| 超碰免费公开在线| 亚洲精品国产一区二区精华液| 精品无码av无码免费专区| 青春草在线视频| 亚洲成av人片一区二区梦乃| 777777av| gogo亚洲高清大胆美女人体| 欧洲一区在线电影| 成人综合久久网| 韩国一区二区三区视频| 精品久久人人做人人爽| 中文字幕天堂网| 制服丝袜日韩| 久久久99久久精品女同性| 久久久久久激情| 日韩午夜免费| 国产精品91久久久久久| 一级黄色短视频| 高潮精品一区videoshd| 蜜桃网站成人| 欧美激情免费| 午夜精品视频一区| 欧美亚洲日本在线观看| 国产精品日韩精品在线播放| 亚洲国产精品专区久久| 精品日韩在线视频| 亚洲色图插插| 欧美性受xxx| 一本到在线视频| 国产精品香蕉一区二区三区| 鲁丝片一区二区三区| 日本三级在线播放完整版| 亚洲午夜av在线| 波多野结衣天堂| 一区二区三区亚洲变态调教大结局| 日韩成人在线免费观看| 久久一级免费视频| 99热在线精品观看| 成人黄色av网站| 香蕉国产在线视频| 亚洲人成在线播放网站岛国| www.玖玖玖| 精品一级视频| 国产午夜精品一区理论片飘花 | 亚洲网站在线| 国产精品视频在线观看| 色一情一乱一乱一区91av| 国产精品久久久久影视| 欧美成人国产va精品日本一级| 青娱乐av在线| 久久精品理论片| 久久精品国产美女| 午夜小视频福利在线观看| 欧洲另类一二三四区| 制服丝袜第一页在线观看| 99久久九九| 国产成人久久久| 人妻与黑人一区二区三区| 国产精品理论片| 免费午夜视频在线观看| 深夜在线视频| 日韩女优毛片在线| 九九热久久免费视频| 午夜在线一区二区| 国产一级二级三级精品| 麻豆影院在线| 欧美日韩精品一区二区三区| 免费在线观看污| av一区二区在线播放| 国内精品视频一区| 亚洲第一页综合| 亚洲欧美在线高清| 亚洲一区二区福利视频| 久久中文字幕av一区二区不卡| www.日韩免费| 波多野结衣日韩| 久久久久久久综合色一本| 黄色av网址在线播放| 一区二区三区视频免费视频观看网站| 中文字幕日韩精品在线观看| 无码人妻丰满熟妇奶水区码| 99精品国产91久久久久久 | x88av在线| 久久aⅴ国产紧身牛仔裤| 国产欧美韩日| 国产传媒在线观看| 亚洲第一精品夜夜躁人人爽| 久久综合综合久久| 成人免费av在线| 国内精品在线观看视频| 精品三级av在线导航| 91地址最新发布| 你懂的在线播放| 在线日韩一区二区| 国产7777777| 久久er精品视频| 影音先锋男人的网站| 一区二区三区免费在线看| 午夜精品一区二区三区在线播放| 亚州精品国产精品乱码不99按摩| 欧美日韩国产一区在线| 国产jjizz一区二区三区视频| 一本色道久久精品| 欧美午夜精品久久久久免费视| 欧美成a人片在线观看久| 色av吧综合网| www.久久色| 亚洲18女电影在线观看| 熟女高潮一区二区三区| 卡一卡二国产精品| 欧美 亚洲 视频| 美女扒开腿让男人桶爽久久动漫| 欧美一级成年大片在线观看| a√在线中文网新版址在线| 欧美一区二区三区播放老司机| 欧美精品久久久久性色| 2020日本不卡一区二区视频| 午夜免费福利在线| 女人色偷偷aa久久天堂| 极品日韩久久| 欧美啪啪网站| 欧美激情在线一区| 国产福利小视频在线观看| 91精品久久久久久久99蜜桃| 日本少妇吞精囗交| 欧美韩日一区二区三区四区| 亚洲精品无码久久久久久久| 妖精视频成人观看www| 亚洲欧洲国产日韩精品| 国产成人精品亚洲线观看| 国产福利精品在线| 国产探花视频在线观看| 中文字幕日韩精品在线| 三级网站免费观看| 欧美日本国产一区| 国产精品视频久久久久久久| 国产精品久久久爽爽爽麻豆色哟哟| 韩国三级视频在线观看| 日韩电影在线观看电影| 欧美黑人在线观看| 日韩精品诱惑一区?区三区| 成人综合电影| 2020国产精品小视频| 欧美亚洲成人免费| 伊人春色在线观看| 正在播放亚洲1区| 青青草视频在线免费观看| 欧美一卡2卡三卡4卡5免费| 天天操天天干天天摸| 亚洲福利一区二区| 男女做暖暖视频| 中文字幕乱码亚洲精品一区| av无码一区二区三区| 狠狠色丁香婷综合久久| a在线观看免费视频| 每日更新成人在线视频| 美女扒开大腿让男人桶| 午夜影院欧美| 日韩偷拍一区二区| 妖精一区二区三区精品视频| 国产日韩欧美综合精品| 国产电影一区二区| 国产伦精品一区二区三区精品视频| 在线男人天堂| 欧美一级免费看| 国产美女高潮在线观看| 久久久久久久网站| 中文字幕在线播放网址| 久久精品中文字幕| 337p日本欧洲亚洲大胆鲁鲁| 亚洲区在线播放| 日韩一二三四| 亚洲女同精品视频| 日本一二三区在线视频| 亚洲精品国产精品国自产在线| 国 产 黄 色 大 片| 日韩精品自拍偷拍| 亚洲精品久久久久久动漫器材一区| 91麻豆精品国产91久久久资源速度 | 久久久久久久久毛片| 中文字幕一区av| 女人18毛片毛片毛片毛片区二| 欧美韩国一区二区| 久久精品色妇熟妇丰满人妻| 中文字幕第一区二区| 极品久久久久久久| 国产精品久久看| 国产人妻精品一区二区三区不卡| 亚洲人亚洲人成电影网站色| 久久国产精品国语对白| 亚洲视频每日更新| 久久精品www| 亚洲高清不卡在线观看| 国产成人无码精品久在线观看| 精品久久久久久| 免费观看日批视频| 欧美日韩午夜影院| 国产欧美日韩综合精品一区二区三区| 91精品福利在线一区二区三区 | 五月婷婷丁香在线| 欧美日韩卡一卡二| 国产人妖在线播放| 亚洲第一区中文字幕| 欧洲亚洲在线| 日日噜噜噜夜夜爽亚洲精品| 18加网站在线| 97超级碰碰碰| 97精品国产99久久久久久免费| 91久久国产综合久久91精品网站| 日韩亚洲精品在线观看| 久久久com| 成人动漫免费在线观看| 麻豆中文字幕在线观看| 亚洲激情社区| 久久精品午夜福利| 国产在线播放一区| 少妇一级淫免费观看| 中文字幕欧美日韩一区| 久久久久成人片免费观看蜜芽| 欧美性色视频在线| 91在线你懂的| 亚洲国产日韩欧美在线动漫| 国内av一区二区三区| 久久不射电影网| 高清av不卡| 亚洲一区二区在线| 蜜桃国内精品久久久久软件9| 亚洲激情一区二区三区| 国产精品99一区二区| 国产免费视频传媒| 国产精品一区二区久久不卡| 全黄一级裸体片| 一区二区三区鲁丝不卡| 欧美超碰在线观看| 欧美xxx久久| av网页在线| 97不卡在线视频| 欧美激情精品| 视频一区视频二区视频| 伊人久久亚洲美女图片| 亚洲欧美日韩精品一区| 99riav久久精品riav| 国产精品丝袜一区二区| 色偷偷88欧美精品久久久| 国产成年妇视频| 中文字幕日韩精品在线观看| 一个人看的www视频在线免费观看| 成人自拍性视频| 精品国内自产拍在线观看视频| 六月婷婷激情综合| 九色|91porny| 三上悠亚影音先锋| 亚欧色一区w666天堂| 97人妻精品一区二区三区| 亚洲欧洲在线看| av小说在线播放| 114国产精品久久免费观看| 欧美一级本道电影免费专区| 大陆极品少妇内射aaaaa| 国产精品自拍av| 97在线观看免费高| 欧美日韩电影一区| 国产黄色免费在线观看| 日韩av理论片| 亚洲人成网亚洲欧洲无码| 久久久久久免费看| 粉嫩蜜臀av国产精品网站| 国产又黄又爽又无遮挡| 91精品在线免费| 男人和女人做事情在线视频网站免费观看| 国产精品mp4| 国产va免费精品观看精品视频 | 成人夜色视频网站在线观看| 国模无码国产精品视频| 欧美嫩在线观看| 日本精品在线| 成人高清视频观看www| 色小子综合网| 红桃视频 国产| 欧美国产日韩精品免费观看| 日韩熟女一区二区| 亚洲性夜色噜噜噜7777| 伊人久久高清| 亚洲欧美影院| 国产一区二区日韩精品| 亚洲av鲁丝一区二区三区 | 久久这里精品| 国产福利视频一区二区| 日韩av免费大片| 天天综合成人网| 亚洲伊人伊色伊影伊综合网| 动漫av一区二区三区| 午夜精品福利在线观看| 日韩三级毛片| 亚洲成人福利在线观看| 一色桃子久久精品亚洲| 99久久免费国产精精品| 欧美激情喷水视频| 亚洲成aⅴ人片久久青草影院| 成人久久久久久久久| 国产精品视频免费看| 国产又黄又爽视频| 欧美国产日韩免费| 网友自拍一区| 天天干天天干天天干天天干天天干| 国产精品女上位| www.com欧美| 欧美最顶级的aⅴ艳星| 成人av国产| 女同性αv亚洲女同志| 欧美视频一二三| 午夜视频在线观看网站| 超碰97在线资源| 久久精品亚洲一区二区| 午夜精品久久久久99蜜桃最新版| 日韩一级精品视频在线观看| 亚洲涩涩在线| 特级毛片在线免费观看| 波多野结衣中文一区| 久久久精品毛片| 久久综合九色九九| 免费成人av| 国产探花一区二区三区| 欧美日韩免费在线| 黄在线免费看| 精选一区二区三区四区五区| 久久精品国产**网站演员| 国产稀缺真实呦乱在线| 一区二区三区视频免费| 精品国产乱码久久久久久樱花| 欧美啪啪免费视频| 国产精品传媒入口麻豆| 天天色棕合合合合合合合| 91精品视频在线播放| 久久久天天操| 久久久国产成人| 日韩亚洲综合在线| 亚洲色图丝袜| 亚洲成年人在线观看|