- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
在我正在开发的框架中,用户可以选择在后台运行某个耗时的任务,同时执行其他操作。该任务计算一系列结果。在某些时候,当他/她需要后台任务的结果时,再等一段时间是可以接受的,直到:
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/
我正在使用 Java 编写一个时钟程序,该程序能够“滴答作响”,但它存在问题。我认为它与 getter 和 setter 或 toString() 方法有关。 计数器类 package clock;
const Index = () => { // Ref Links const frefLinks = { 1: useRef(1), 2: useRef(2), 3: useRef(3
所以我读了here不能 pickle 装饰函数。确实: import multiprocessing as mp def deco(f): def wrapper(*args, **kwarg
我在go1.11.2 linux/amd64 版本。当包godog使用 go get github.com/DATA-DOG/godog/ 安装,godog 可执行文件在 $GOPATH/bin/中创
如何正确压缩字符串,以便 PHP 能够解压缩? 我试过这个: public static byte[] compress(String string) throws IOException {
我们这里的问题是表明 在测试中使用 Kleene 代数。 在 b 的值由 p 保留的情况下,我们有交换条件 bp = pb;两个程序之间的等价性简化为等式 在 b 的值不被 p 保留的情况下,我们有交
我有一个与我的网络相关的非常奇怪的问题,我在具有多个接口(interface)的 VirtualBox 上安装了 RDO Grizzly OpenStack。 虚拟盒子: eth0 - managem
我正在尝试使用 Passport.js授权谷歌OAuth2在 Node.js .我整个星期都在尝试让它工作,但不知道为什么它不工作,所以现在我求助于 stack 寻求一些潜在的帮助。我已经尝试了所有在
我是一名优秀的程序员,十分优秀!