根据我的经验,超时时间通常是任意选择的,因为它们不是时间关键型的。 如果我选择了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();
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) {
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的代价。这并不是微不足道的,但如果做得正确,可以给你带来两者的某些好处(如果效率低下,则两面都不如)。
你可以实现自己的线程逻辑,前提是你有大量的小任务。例如,如果你想轮询10件事情,你可以只使用一个CPU。
isResponseArrived=true
?如果它是由网络响应设置的,最优的方式将是使用超时读取输入通道。 - khachik