只读事务上下文_我可以/应该在事务上下文中使用并行流吗?
只讀事務(wù)上下文
介紹
長話短說,您不應(yīng)在并行流中使用事務(wù)。 這是因為并行流中的每個線程都有其自己的名稱,因此它確實參與了事務(wù)。
Streams API旨在在某些準則下正常工作。 實際上,為了受益于并行性,不允許每個操作更改共享對象的狀態(tài)(此類操作稱為無副作用)。 如果您遵循此準則,并行流的內(nèi)部實現(xiàn)將巧妙地拆分數(shù)據(jù),將不同部分分配給獨立線程,并合并最終結(jié)果。
這主要是由于實現(xiàn)事務(wù)的方式而產(chǎn)生的。 在某種程度上,ThreadLocal變量用于標(biāo)記參與事務(wù)的每個方法。 ThreadLocal變量無法將其變量保持在并行流中。 為了證明我已經(jīng)創(chuàng)建了以下測試
import org.junit.Assert; import org.junit.Test; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.IntStream; public class ThreadNameTest { @Test public void threadLocalTest(){ ThreadContext.set( "MAIN" ); AtomicBoolean hasNamechanged = new AtomicBoolean( false ); IntStream.range( 0 , 10000000 ).boxed().parallel().forEach(n->{ if (! "MAIN" .equals(ThreadContext.get())){ hasNamechanged.set( true ); } }); Assert.assertTrue(hasNamechanged.get()); } private static class ThreadContext { private static ThreadLocal<String> val = ThreadLocal.withInitial(() -> "empty" ); public ThreadContext() { } public static String get() { return val.get(); } public static void set(String x) { ThreadContext.val.set(x); } } }IntStream.range值越高,則測試成功的可能性就越大。
現(xiàn)在看看這個github項目https://github.com/diakogiannis/transactionplayground/
TransactionPlayground項目
我創(chuàng)建了一種以4種不同方式加載貓的服務(wù)
也有2個輔助呼叫
開始項目
請執(zhí)行mvn clean package wildfly-swarm:run
正常訂購
呼叫curl -I -X GET http://localhost:8080/api/cats/all ,然后curl -X GET http://localhost:8080/api/cats/
正常,無訂單,又稱平行
調(diào)用clean curl -I -X DELETE http://localhost:8080/api/cats/調(diào)用curl -I -X GET http://localhost:8080/api/cats/all-parallel然后curl -X GET http://localhost:8080/api/cats/
預(yù)期的結(jié)果是看到貓的清單。 無需訂購。 這就是為什么并行流先到先服務(wù)并從列表中隨機讀取的原因。
正常,例外
調(diào)用clean curl -I -X DELETE http://localhost:8080/api/cats/調(diào)用curl -I -X GET http://localhost:8080/api/cats/all-exception然后curl -X GET http://localhost:8080/api/cats/
預(yù)期的結(jié)果是一個空列表。 這是因為該事務(wù)被標(biāo)記為回滾,所以jdbc事務(wù)也被回滾,因此所有條目都沒有按照ACID模型持久化到數(shù)據(jù)庫中。
平行例外
調(diào)用clean curl -I -X DELETE http://localhost:8080/api/cats/調(diào)用curl -I -X GET http://localhost:8080/api/cats/all-parallel-exception然后curl -X GET http://localhost:8080/api/cats/
預(yù)期的結(jié)果不是一個空列表。 這是因為并行流中的每個線程都會打開自己的jdbc事務(wù),并在完成后進行提交。 因此,每次執(zhí)行此操作時,都會顯示一些貓,直到出現(xiàn)異常并停止執(zhí)行。 回滾僅在一個線程中進行。
翻譯自: https://www.javacodegeeks.com/2019/09/should-parallel-streams-transaction-context.html
只讀事務(wù)上下文
總結(jié)
以上是生活随笔為你收集整理的只读事务上下文_我可以/应该在事务上下文中使用并行流吗?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 荣耀V Purse新机到手 日常该如何保
- 下一篇: 谷歌发布 Chrome 117 浏览器更