我可以/应该在事务上下文中使用并行流吗?
介紹
長話短說,您不應在并行流中使用事務。 這是因為并行流中的每個線程都有其自己的名稱,因此它確實參與了事務。
Streams API旨在在某些準則下正常工作。 實際上,為了受益于并行性,不允許每個操作更改共享對象的狀態(此類操作稱為無副作用)。 如果您遵循此準則,并行流的內部實現將巧妙地拆分數據,將不同部分分配給獨立線程,并合并最終結果。
這主要是由于實現事務的方式而產生的。 排序上,ThreadLocal變量用于標記參與事務的每個方法。 ThreadLocal變量無法將其變量保持在并行流中。 為了證明我已經創建了以下測試
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值越高,則測試成功的可能性就越大。
現在看看這個github項目https://github.com/diakogiannis/transactionplayground/
TransactionPlayground項目
我創建了一種以4種不同方式加載貓的服務
也有2個輔助呼叫
開始項目
請執行mvn clean package wildfly-swarm:run
正常訂購
呼叫curl -I -X GET http://localhost:8080/api/cats/all ,然后curl -X GET http://localhost:8080/api/cats/
正常,無訂單,又稱平行
調用clean curl -I -X DELETE http://localhost:8080/api/cats/調用curl -I -X GET http://localhost:8080/api/cats/all-parallel然后curl -X GET http://localhost:8080/api/cats/
預期的結果是看到貓的清單。 無需訂購。 這就是為什么并行流先到先服務并從列表中隨機讀取的原因。
正常,例外
調用clean curl -I -X DELETE http://localhost:8080/api/cats/調用curl -I -X GET http://localhost:8080/api/cats/all-exception然后curl -X GET http://localhost:8080/api/cats/
預期的結果是一個空列表。 這是因為該事務被標記為回滾,所以jdbc事務也被回滾,因此所有條目都沒有按照ACID模型持久化到數據庫中。
平行例外
調用clean curl -I -X DELETE http://localhost:8080/api/cats/調用curl -I -X GET http://localhost:8080/api/cats/all-parallel-exception然后curl -X GET http://localhost:8080/api/cats/
預期的結果不是一個空列表。 這是因為并行流中的每個線程都會打開自己的jdbc事務,并在完成后進行提交。 因此,每次執行此操作時,都會顯示一些貓,直到出現異常并停止執行為止。 回滾僅在一個線程中進行。
翻譯自: https://www.javacodegeeks.com/2019/09/should-parallel-streams-transaction-context.html
總結
以上是生活随笔為你收集整理的我可以/应该在事务上下文中使用并行流吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ddos攻击需要哪些工具(ddos需要什
- 下一篇: JMetro版本11.5.10和8.5.