根据我的经验,超时是任意选择的,例如不是时间关键的。如果我选择 1000 毫秒的超时并且它需要 1001 毫秒,那么影响应该是微不足道的。对于实现超时,我建议使实现尽可能简单。
您可以使用 ScheduledExecutorService 实现超时,例如
final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
public void addTimeoutForTask(final Future future, int timeOutMS) {
ses.schedule(new Runnable() {
@Override
public void run() {
future.cancel(true);
}
}, timeOutMS, TimeUnit.MILLISECONDS);
}
如果您正在执行一些非阻塞操作并且您希望它超时,您可以这样做。
interface TimedPoller {
public void poll();
/**
* @return is it now closed.
*/
public boolean checkTimeout(long nowNS);
}
private final Set<TimedPoller> timedPollers = new LinkedHashSet<>();
private volatile TimedPoller[] timedPollersArray = {};
public void add(TimedPoller timedPoller) {
synchronized (timedPollers) {
long nowNS = System.nanoTime();
if (!timedPoller.checkTimeout(nowNS) && timedPollers.add(timedPoller))
timedPollersArray = timedPollers.toArray(new TimedPoller[timedPollers.size());
}
}
public void remove(TimedPoller timedPoller) {
synchronized (timedPollers) {
if (timedPollers.remove(timedPoller))
timedPollersArray = timedPollers.toArray(new TimedPoller[timedPollers.size());
}
}
private volatile boolean running = true;
public void run() {
while (running) {
// check the timeout for every 1000 polls.
for (int i = 0; i < 1000; i += timedPollersArray.length) {
TimedPoller[] pollers = timedPollersArray;
for (TimedPoller poller : pollers) {
poller.poll();
}
}
long nowNS = System.nanoTime();
TimedPoller[] pollers = timedPollersArray;
for (TimedPoller poller : pollers) {
if (poller.checkTimeout(nowNS))
remove(poller);
}
}
}
要么放弃 CPU,要么不放弃。如果你放弃 CPU,其他线程可以运行,但你会得到一个延迟,然后才能再次运行。或者你没有放弃 CPU 来提高你的响应时间,但是另一个线程无法运行。
看来您希望能够让其他东西运行,而无需放弃 CPU。这不是微不足道的,但如果做得正确,可以给你带来两者的一些好处(或者如果没有有效地完成,两者都会带来最坏的结果)
你可以做的是实现你自己的线程逻辑,前提是你有很多小任务,例如你想轮询十个你可以只使用一个 CPU 的东西。