听起来你所追求的可以通过 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]