gpt4 book ai didi

java - 如何在 Java 中对计算进行时间限制并能够获得到目前为止计算的所有结果,即使时间预算结束(超时)?

转载 作者:搜寻专家 更新时间:2023-11-01 03:30:16 24 4
gpt4 key购买 nike

在我正在开发的框架中,用户可以选择在后台运行某个耗时的任务,同时执行其他操作。该任务计算一系列结果。在某些时候,当他/她需要后台任务的结果时,再等一段时间是可以接受的,直到:

  • a) 发生超时(在这种情况下,用户希望获得到目前为止计算的所有结果,如果它们存在的话);或者

  • b) 达到最大数量或计算结果(正常结束),

以先发生者为准。

陷阱是:即使发生超时,用户仍然想要到目前为止计算的结果。

我尝试使用 Future<V>.get(long timeout, TimeUnit unit) 来做到这一点和一个 Callable<V> -派生类,但碰巧发生 TimeoutException 时通常意味着任务过早完成,因此没有可用结果。因此我不得不添加一个 getPartialResults()方法(参见下面的 DiscoveryTask),恐怕这种用法对于潜在用户来说太违反直觉了。

发现调用:

public Set<ResourceId> discover(Integer max, long timeout, TimeUnit unit)
throws DiscoveryException
{
DiscoveryTask task = new DiscoveryTask(max);
Future<Set<ResourceId>> future = taskExec.submit(task);
doSomethingElse();
try {
return future.get(timeout, unit);
} catch (CancellationException e) {
LOG.debug("Discovery cancelled.", e);
} catch (ExecutionException e) {
throw new DiscoveryException("Discovery failed to execute.", e);
} catch (InterruptedException e) {
LOG.debug("Discovery interrupted.", e);
} catch (TimeoutException e) {
LOG.debug("Discovery time-out.");
} catch (Exception e) {
throw new DiscoveryException("Discovery failed unexpectedly.", e);
} finally {
// Harmless if task already completed
future.cancel(true); // interrupt if running
}
return task.getPartialResults(); // Give me what you have so far!
}

发现实现:

public class DiscoveryTask extends Callable<Set<ResourceId>> 
implements DiscoveryListener
{
private final DiscoveryService discoveryService;
private final Set<ResourceId> results;
private final CountDownLatch doneSignal;
private final MaximumLimit counter;
//...
public DiscoveryTask(Integer maximum) {
this.discoveryService = ...;
this.results = Collections.synchronizedSet(new HashSet<ResourceId>());
this.doneSignal = new CountDownLatch(1);
this.counter = new MaximumLimit(maximum);
//...
}

/**
* Gets the partial results even if the task was canceled or timed-out.
*
* @return The results discovered until now.
*/
public Set<ResourceId> getPartialResults() {
Set<ResourceId> partialResults = new HashSet<ResourceId>();
synchronized (results) {
partialResults.addAll(results);
}
return Collections.unmodifiableSet(partialResults);
}

public Set<ResourceId> call() throws Exception {
try {
discoveryService.addDiscoveryListener(this);
discoveryService.getRemoteResources();
// Wait...
doneSignal.await();
} catch (InterruptedException consumed) {
LOG.debug("Discovery was interrupted.");
} catch (Exception e) {
throw new Exception(e);
} finally {
discoveryService.removeDiscoveryListener(this);
}
LOG.debug("Discovered {} resource(s).", results.size());
return Collections.unmodifiableSet(results);
}

// DiscoveryListener interface
@Override
public void discoveryEvent(DiscoveryEvent de) {
if (counter.wasLimitReached()) {
LOG.debug("Ignored discovery event {}. "
+ "Maximum limit of wanted resources was reached.", de);
return;
}
if (doneSignal.getCount() == 0) {
LOG.debug("Ignored discovery event {}. "
+ "Discovery of resources was interrupted.", de);
return;
}
addToResults(de.getResourceId());
}

private void addToResults(ResourceId id) {
if (counter.incrementUntilLimitReached()) {
results.add(id);
} else {
LOG.debug("Ignored resource {}. Maximum limit reached.",id);
doneSignal.countDown();
}
}
}

在 Brian Goetz 等人的 Java Concurrency in Practice 一书的第 6 章中,作者展示了相关问题的解决方案,但在那种情况下,所有结果都可以并行计算,这不是我的情况。准确地说,我的结果取决于外部来源,所以我无法控制它们何时出现。我的用户在调用任务执行之前定义了他想要的最大结果数,以及她同意在准备好获取结果后等待的最大时间限制。

你觉得这样可以吗?你会做不同的事吗?有没有更好的方法?

最佳答案

将(更短的)超时传递给任务本身,并让它在达到此“软超时”时过早返回。然后结果类型可以有一个标志来告诉结果是否完美:

Future<Result> future = exec.submit(new Task(timeout*.9));
//if you get no result here then the task misbehaved,
//i.e didn't obey the soft timeout.
//This should be treated as a bug
Result result = future.get(timeout);
if (result.completedInTime()) {
doSomethingWith(result.getData());
} else {
doSomethingElseWith(result.getData());
}

关于java - 如何在 Java 中对计算进行时间限制并能够获得到目前为止计算的所有结果,即使时间预算结束(超时)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2267448/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com