有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何保持一个固定大小的列表库?

我正在读取一个很大的URL文件,并向服务发出请求。请求由返回ListenableFuture的客户端执行。现在我想保留一个ListenableFuture池,例如,最大限度地同时执行N期货

我看到的问题是,由于第三方库,我无法控制ExecutorService中执行的ListenableFuture。否则我会创建一个FixedSizePool并创建我自己的Callable

1)一个幼稚的实现是产生N期货,然后使用AllAsList,这将满足固定大小的标准,但让所有人等待最慢的请求。 无序处理是可以的

2)一个稍微好一点的天真选择是使用第一个想法,并将其与速率限制器结合起来,通过设置Nrate,使并发请求的数量非常接近所需的池大小。但我实际上并不是在寻找一种限制通话的方法,例如使用RateLimiter

3)最后一个选项是生成N期货,并有一个生成新期货的回调。这满足了固定大小的标准,并最大限度地减少了空闲时间,但在那里我不知道如何检测我的程序是否结束,即关闭文件

4)一种与ListenableFuture无关的方法是直接.get()结果,并通过创建一个简单的Threadpool来处理尴尬的并行任务

为了知道作业队列是空的,即关闭文件,我考虑使用CountdownLatch。这应该适用于许多选项


共 (3) 个答案

  1. # 1 楼答案

    嗯,你觉得只用java.util.concurrent.Semaphore怎么样

    Semaphore gate = new Semaphore(10);
    Runnable release = gate::release; // java 8 syntax.
    Iterator<URL> work = ...;
    while(work.hasNext() && gate.acquire()) {
      ListenableFuture f = ThirdPartyLibrary.doWork(work.next());
      f.addListener( release, MoreExecutors.sameThreadExecutor() );
    }
    

    您可以通过使用Futures.addCallback(ListenableFuture, FutureCallback)来添加其他侦听器来处理结果,只要您小心地release()处理成功和错误

    这可能有用

  2. # 2 楼答案

    你的选择3听起来很合理。如果您想清楚地检测所有请求何时完成,一种简单的方法是创建一个新的SettableFuture来表示完成

    当您的回调尝试从队列中获取下一个请求,并发现它为空时,您可以在将来调用set(),通知正在等待所有请求完成的任何内容。传播来自单个请求的异常留给读者作为练习

  3. # 3 楼答案

    使用FixedSizePool来完成尴尬的并行任务,并立即.get()预测未来的结果

    这简化了代码,并允许每个工作人员拥有可修改的上下文