我们使用ExecutorService
并行地对云存储进行各种REST调用,我们担心池可能会忙于被阻止的调用,这些调用已经失控,然后长时间阻止较新的调用(云超时可能在经历所有重试后几分钟).当然,我们总是可以添加越来越多的线程,但我用C++实现的一种解决方案是,如果任务尚未开始,就让Future.get()
在调用者线程中运行.Java almost在Executors.newWorkStealingQueue()
中实现了这一点,但只有在调用方本身是池线程时,才会启用调用方逻辑:
class ForkJoinTask {
private int awaitDone(...) {
...
if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
// execute in caller thread
这就是工作窃取防止递归算法耗尽线程的方式.但如果调用方是普通线程,则不会触发此逻辑.ForkJoinPool
也没什么不同,因为Executors.newWorkStealingQueue()
只是一个包装.Java中有没有什么东西支持我想要的东西?
PS:我们还不能使用JDK 21的虚拟线程:-(
更新:更多关于用例的解释.我们发现,为了回答有关云存储的某些问题,例如,应该将此路径视为目录还是文件,我们必须问几个问题:
- 是否存在具有该名称的斑点?
- 是否存在名称后跟/的blob?
- 是否存在以该路径为前缀的其他BLOB?
执行器允许我们并行地提出这些问题,并减少延迟.因此,我们有一个共享的执行者,每个人都可以问这些关于云存储终端的问题.但是...有时,某个终端会崩溃,在恢复或超时之前不回答问题,这可能需要几分钟的时间.当这种情况发生时,我们不希望延迟的请求阻塞其他所有人的执行程序,并使every个请求等待."调用者忙时执行"模式给了我们一个安全阀,在几分钟内一切都会稍微慢一点,但不会慢lot分钟.