获取 Future<T> 对象的进度能力

15

涉及到 java.util.concurrent 包和 Future 接口,我发现(如果我没有错的话),仅能使用 SwingWorker 实现类才能启动长时间任务并查询其进度。

这引出以下问题:

在非 GUI、非 Swing 应用程序(比如控制台应用程序)中,是否有一种方法可以在后台启动长时间任务并允许其他线程检查进度?我认为,这种能力不应该被限制在 Swing/GUI 应用程序中。否则,唯一可用的选项是通过 ExecutorService::submit 来提交任务,它返回一个 Future 对象。但是,基本的 Future 接口不允许监视进度。


2
请参见https://dev59.com/RkvSa4cB1Zd3GeqPbyG5 - Mark
3个回答

5
显然,Future对象只适用于阻塞并接收结果。
您提交的Runnable或Callable对象必须知道如何提供此进度(完成百分比、尝试次数计数、状态(枚举?)等),并将其作为API调用提供给对象本身,或者发布在某些查找资源中(如果需要,则在内存映射或数据库中)。 为简单起见,我倾向于喜欢对象本身,特别是因为您很可能需要一个句柄(id)来查找对象或对对象本身的引用。
这意味着您有三个线程在操作。1个用于实际工作,1个在等待结果时被阻塞,另一个是监视线程。最后一个线程可以根据您的要求共享。

2
我希望有一种标准并发框架的方法,可以在长时间运行的任务进度更新时保持客户端程序不必担心正确协调和同步所有内容。对我来说,似乎可以构思一个扩展版的Future<T>接口,支持以下内容:public short progress();除了通常的isDone()get()方法。 显然,progress()的实现需要直接轮询对象,因此Future<T>可能需要指定为Future<T extends CanReportProgress>,其中CanReportProgress是以下接口:
public interface CanReportProgress {
    public short progress();
}

这引出一个问题,为什么要费心去使用Future对象来获取进度,而不是直接调用对象本身呢?我不知道。我需要再思考一下。可以说这更贴近当前的契约/语义,即Callable对象在调用ExecutorService::submit / execute后,客户端程序员不会再次访问它本身。

我不知道除了参考 SwingWorker(1.6 JDK 的一部分)作为非 Swing 版本的例子之外,JDK 内是否有其他东西可以帮助你。它使用 RunnableFuture<T> 和 getProgress()(带有事件通知)。对我来说,这听起来是一个很好的起点,因为它是一个已知的量,并且经过多年由更伟大的思想进行开发和测试。祝你好运! - Matt
6
请注意,Future<T>中的T代表返回值的类型。在任务完成之前,您无法访问T。因此,将T扩展为CanReportProgress是没有意义的。 - Anderson

2
在我的情况中,我将一个包含要处理的对象的HashSet作为参数传递给方法,并将其创建为调用类中的实例变量。当异步方法在处理一个对象之后删除它们时,可以在调用方法中检索剩余Map的大小。我认为通常通过引用传递对象可以解决这个问题。

我正要在答案中说同样的话。只有一件事,在某些情况下,应该控制方法参数的访问,以避免多个线程之间的竞争条件。或者使用线程和进度对象的映射也可以。 - PhoenixPerson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接