想象我有一個類,它的方法 ( process) 可以被并發呼叫。這個方法做了一些doProcess不能并發執行的處理()。此外,如果process方法被呼叫,但是處理 ( doProcess) 已經在進行中 - 呼叫process應該等到已經開始的處理 ( doProcess) 完成然后回傳(不開始新的處理 - doProcess)。如果還沒有執行緒process進行實際處理 ( doProcess),則呼叫方法只會進行實際處理 ( ) doProcess。
// Just imaginary example to illustrate the idea
class MyResource() {
val lock = MyLock()
fun process() {
if (!lock.isLocked) {
lock.lock()
doProcess()
lock.unlock()
}
lock.awaitUnlocked()
}
private fun doProcess() {
// actual processing
}
}
上面假想示例中描述的并發問題的預期并發 (java.util.concurrent) 原語是什么?我想過ReentrantLock但它不提供awaitUnlocked。而且java.util.concurrent.locks.Condition似乎太低級了這個簡單的用例。
uj5u.com熱心網友回復:
聽起來你所追求的可以用 ConcurrentMap 來完成——更具體地說,computeIfAbsent。
例如,您可以運行下面的代碼。有點像快取 - 如果你想要的東西可用,只需回傳它。否則等待哪個執行緒先到達那里先計算它。
import java.time.Instant;
import java.util.concurrent.*;
public class ConcurrencyTest
{
private final ConcurrentMap<String, String> processItems = new ConcurrentHashMap<>();
public String process()
{
return processItems.computeIfAbsent("doProcess", k -> doProcess());
}
private String doProcess()
{
try
{
System.out.println(Instant.now() " -> doProcess() Starting some work on " Thread.currentThread());
Thread.sleep(100);
System.out.println(Instant.now() " -> doProcess() Finished some work on " Thread.currentThread());
return Instant.now().toString();
}
catch(Exception e)
{
throw new RuntimeException("Unexpected Exception : " e, e);
}
}
/**
* And to test it out.
*
* @param args
* @throws Exception
*/
public static void main(String... args) throws Exception
{
final int THREADS = 10;
final ConcurrencyTest test = new ConcurrencyTest();
final ExecutorService execs = Executors.newFixedThreadPool(THREADS);
final CountDownLatch startingGun = new CountDownLatch(1);
for (int i = 0; i < THREADS; i )
{
execs.submit(() -> {
System.out.println(Instant.now() " -> Thread -> " Thread.currentThread() " - Awaiting Starting Gun");
try
{
startingGun.await();
}
catch (InterruptedException e)
{
throw new RuntimeException("Failure waiting for the starting gun.");
}
System.out.println(Instant.now() " -> Running Thread -> " Thread.currentThread());
String val = test.process();
System.out.println(Instant.now() " -> Got back " val " -> " Thread.currentThread());
});
}
System.out.println("All tasks submitted.. waiting for 5 seconds then firing the starting gun. ");
Thread.sleep(5_000);
startingGun.countDown();
execs.shutdown();
}
}
給我下面的輸出。正如您所看到的,只有一個執行緒最終執行了相關代碼。剩下的就等著吧。
All tasks submitted.. waiting for 5 seconds then firing the starting gun.
2021-12-30T17:59:51.696626Z -> Thread -> Thread[pool-1-thread-3,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696606Z -> Thread -> Thread[pool-1-thread-8,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696245Z -> Thread -> Thread[pool-1-thread-10,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696231Z -> Thread -> Thread[pool-1-thread-6,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696627Z -> Thread -> Thread[pool-1-thread-5,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696633Z -> Thread -> Thread[pool-1-thread-4,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696274Z -> Thread -> Thread[pool-1-thread-2,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696231Z -> Thread -> Thread[pool-1-thread-1,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696620Z -> Thread -> Thread[pool-1-thread-7,5,main] - Awaiting Starting Gun
2021-12-30T17:59:51.696261Z -> Thread -> Thread[pool-1-thread-9,5,main] - Awaiting Starting Gun
2021-12-30T17:59:56.695927Z -> Running Thread -> Thread[pool-1-thread-5,5,main]
2021-12-30T17:59:56.696031Z -> Running Thread -> Thread[pool-1-thread-6,5,main]
2021-12-30T17:59:56.695968Z -> Running Thread -> Thread[pool-1-thread-4,5,main]
2021-12-30T17:59:56.695863Z -> Running Thread -> Thread[pool-1-thread-10,5,main]
2021-12-30T17:59:56.695832Z -> Running Thread -> Thread[pool-1-thread-8,5,main]
2021-12-30T17:59:56.696063Z -> Running Thread -> Thread[pool-1-thread-2,5,main]
2021-12-30T17:59:56.696133Z -> Running Thread -> Thread[pool-1-thread-3,5,main]
2021-12-30T17:59:56.696254Z -> Running Thread -> Thread[pool-1-thread-9,5,main]
2021-12-30T17:59:56.696230Z -> Running Thread -> Thread[pool-1-thread-7,5,main]
2021-12-30T17:59:56.696204Z -> Running Thread -> Thread[pool-1-thread-1,5,main]
2021-12-30T17:59:56.714154Z -> doProcess() Starting some work on Thread[pool-1-thread-4,5,main]
2021-12-30T17:59:56.814608Z -> doProcess() Finished some work on Thread[pool-1-thread-4,5,main]
2021-12-30T17:59:56.815375Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-5,5,main]
2021-12-30T17:59:56.815422Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-7,5,main]
2021-12-30T17:59:56.815104Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-8,5,main]
2021-12-30T17:59:56.815065Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-3,5,main]
2021-12-30T17:59:56.815093Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-2,5,main]
2021-12-30T17:59:56.815054Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-4,5,main]
2021-12-30T17:59:56.815420Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-6,5,main]
2021-12-30T17:59:56.815387Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-1,5,main]
2021-12-30T17:59:56.815077Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-9,5,main]
2021-12-30T17:59:56.815435Z -> Got back 2021-12-30T17:59:56.815016Z -> Thread[pool-1-thread-10,5,main]
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/398237.html
標籤:爪哇 科特林 并发 同步 java.util.concurrent
上一篇:這個SpringBoot控制器方法注釋有什么問題?(請求的路徑在類級別定義,路徑變數在方法)
下一篇:如何創建不同列舉類的串列
