天天看點

利用行級鎖判斷多任務并發完成

5台裝置分布式處理30項任務,在30項任務全部處理完成時發送郵件通知,需要在最後一個任務完成時觸發郵件發送動作,實作方式:

1、程式中實作,在程式中synchronized變量表示剩餘任務數;

2、編寫觸發器?相容多資料庫比較麻煩;

3、利用資料庫在程式中判斷,行級鎖保證資料準确性;

1)每次更新已完成任務數後查詢剩餘的任務數,為0時表示任務完成,每個任務需要查詢一次;

2)利用update語句執行成功時傳回更新記錄數,特意讓最後一次更新記錄數為0(不成功),以下為模拟代碼:

/** 處理每個任務,finished為true表示最後一個任務 */
public static int doTask(boolean finished) 
{
    int result = 0;// 執行update語句更新資料庫總記錄數

    Connection conn = null;
    PreparedStatement stmt = null;
    try {
        conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@192.168.100.2:1521:orcl",
                "h2do", "h2do");
        
        if(!finished){
            //
            // TODO:處理其他資料
            // 先送出,減少更新完成任務數的鎖定時間
            conn.commit();
        }

        /* 條件finished=total-1時表示最後一個任務,<total-1時才能更新成功,最後一個任務更新失敗 */
        stmt = conn.prepareStatement(
                "update t_progress set finished = finished + 1 where id = ? and finished < total - ?");
        stmt.setInt(1, 1);
        stmt.setInt(2, finished ? 0 : 1);

        result = stmt.executeUpdate();
        /*
         * 也可在這裡select total-finished from t_progress where id = 1
         * 根據未完成數判斷是否所有任務均已完成
         */
        conn.commit();

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        try {if (null != stmt)stmt.close();} catch (Exception e) {}
        try {if (null != conn)conn.close();} catch (Exception e) {}
    }

    return result;
}

public static void main(String[] args) throws Throwable
{
    oracle.jdbc.driver.OracleDriver.class.newInstance();

    /*模拟30個任務并發處理*/
    for (int i = 0; i < 30; i++) 
    {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int result = doTask(false);
                if (0 == result) {
                    result = doTask(true);
                    if(1 == result){
                        System.out.println("發送所有任務完成郵件。。。");
                    }else{
                        //TODO:記錄日志;
                    }
                }
            }
        }).start();
    }
    
}                

附:

create table t_progress

(

  id       integer not null,

  total    integer not null,

  finished integer default 0 not null,

  constraint pk_t_progress primary key (id)

);

insert into t_progress (ID, TOTAL, FINISHED) values (1, 30, 0);

版權聲明:本文為CSDN部落客「weixin_34292959」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:https://blog.csdn.net/weixin_34292959/article/details/91594247