簡體   English   中英

Java:許多線程中的XA事務傳播

[英]Java: XA Transaction propagation within many threads

如何在Java SE(非Java EE或Spring)中使用事務管理器(如BitronixJBoss TSAtomikos )來支持以下用例:

我們假設我們有以下類:

public class Dao {

    public void updateDatabase(DB db) {
        connet to db
        run a sql
    }

}

我們從中創建一個Java Runnable,如下所示:

public class MyRunnable extends Runnable {

    Dao dao;
    DB db;

    public MyRunnable(Dao dao, DB db) {
        this.dao=dao;
        this.db = db;
    }           

    public run() throws Exception {
        return dao.updateDatabase(db);
    }
}

現在在我們的服務層,我們有另一個類:

public class Service {

    public void updateDatabases() {

        BEGIN TRANSACTION;

        ExecutorService es = Executors.newFixedThreadPool(10);

        ExecutorCompletionService ecs = new ExecutorCompletionService(es);

        List<Future<T>> futures = new ArrayList<Future<T>>(n);

        Dao dao = new Dao();

        futures.add(ecs.submit(new MyRunnable(dao, new DB("db1")));
        futures.add(ecs.submit(new MyRunnable(dao, new DB("db2")));
        futures.add(ecs.submit(new MyRunnable(dao, new DB("db3")));

        for (int i = 0; i < n; ++i) {
            completionService.take().get();
        }

       END TRANSACTION;
    }

}

客戶端可以是Servlet或任何其他多線程環境:

public MyServlet extend HttpServlet {

    protected void service(final HttpServletRequest request, final HttpServletResponse response) throws IOException {

        Service service = new Service();

        service.updateDatabases();

    }

}

BEGIN TRANSACTION和END TRANSACTION部分的正確代碼是什么? 這甚至可行嗎? 如果沒有,需要改變什么? 要求是使updateDatabases()方法保持並發(因為它將同時訪問多個數據庫)和事務性。

這似乎可以使用SubTxThread使用Atomikos完成

//first start a tx
TransactionManager tm = ...
tm.begin();

Waiter waiter = new Waiter();

//the code that calls the first EIS; defined by you
SubTxCode code1 = ...

//the associated thread
SubTxThread thread1 = new SubTxThread ( waiter , code1 );

//the code that calls the second EIS; defined by you
SubTxCode code2 = ...

//the associated thread
SubTxThread thread2 = new SubTxThread ( waiter , code2 );

//start each thread
thread1.start();

thread2.start();

//wait for completion of all calls
waiter.waitForAll();

//check result
if ( waiter.getAbortCount() == 0 ) {
    //no failures -> commit tx
    tm.commit();
} else {
    tm.rollback();
}

XA規范要求所有XA調用都在同一個線程上下文中執行。 詳細說明其原因,因為可以在任何事務分支甚至在線程中創建之前調用提交。

如果您只對如何在JBoss TS中的XA事務中執行這三個調用感興趣

首先確保您的-ds.xml將數據源指定為<xa-datasource>

InitialContext ctx = new InitialContext(parms);
UserTransaction ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");

ut.begin();

//Some Transactional Code

ut.commit();

請記住上面的代碼,您將無法使用ExecutorService來並行化調用。

旁注:我不太了解它,但JTS / OTS聲稱允許多個線程在事務中共享。 我認為它是通過傳播類似於ws-coordination / ws-transaction的事務上下文來實現的,並且得到了JBossTS的支持。 可能是一個紅鯡魚,但如果你沒有時間緊縮,它可能值得研究。

你呢

  1. BEGIN_TRANSATION:連接到服務中的所有3個數據庫,
  2. 將Connection對象(而不是db對象)傳遞給MyRunnable
  3. END_TRANSACTION:調用提交並關閉服務中的所有3個連接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM