面试题答案
一键面试1. 使用定时器(如 setTimeout 或 Timer)
- 原理:在异步操作开始时启动一个定时器,设定一个特定的时间间隔。当定时器超时时,如果异步操作还未完成,就执行超时处理逻辑,比如取消异步任务、抛出超时异常等。例如在 JavaScript 中使用
setTimeout
,代码如下:
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('操作超时'));
}, 5000); // 5 秒后超时
});
// 假设这里有一个异步操作
const asyncOperation = new Promise((resolve) => {
setTimeout(() => {
resolve('操作完成');
}, 10000); // 10 秒后完成
});
Promise.race([asyncOperation, timeoutPromise])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
在上述代码中,timeoutPromise
就是一个超时控制的 Promise,当它先于 asyncOperation
触发时,就会进入 catch
块,提示操作超时。
2. 利用 Future 或 Promise 的超时功能
- 原理:许多编程语言的异步编程框架提供了
Future
或Promise
相关的类,这些类本身就支持设置超时。以 Java 的CompletableFuture
为例,它的orTimeout
方法可以设定一个超时时间,如果CompletableFuture
在规定时间内没有完成,就会抛出TimeoutException
。代码示例如下:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class TimeoutExample {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10000); // 模拟一个耗时操作,10 秒
} catch (InterruptedException e) {
e.printStackTrace();
}
return "操作完成";
});
try {
String result = future.orTimeout(5, TimeUnit.SECONDS).get();
System.out.println(result);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
if (e instanceof TimeoutException) {
System.out.println("操作超时");
}
e.printStackTrace();
}
}
}
这里 orTimeout
方法设置了 5 秒的超时时间,如果 future
在 5 秒内没有完成,就会抛出 TimeoutException
。
3. 自定义超时逻辑结合异步队列
- 原理:维护一个异步任务队列,每个任务记录开始时间。在队列处理过程中,周期性检查任务的执行时间是否超过设定的超时时间。如果超过,则对该任务进行超时处理。例如在 Python 中,可以使用
asyncio
库来自定义实现这样的逻辑。
import asyncio
import time
async def async_task(task_id):
await asyncio.sleep(10) # 模拟一个耗时操作,10 秒
print(f"任务 {task_id} 完成")
async def main():
tasks = []
start_times = {}
timeout = 5 # 5 秒超时
for i in range(3):
task = asyncio.create_task(async_task(i))
tasks.append(task)
start_times[task] = time.time()
while tasks:
for task in tasks.copy():
if time.time() - start_times[task] > timeout:
task.cancel()
tasks.remove(task)
print(f"任务 {tasks.index(task)} 超时取消")
elif task.done():
tasks.remove(task)
await asyncio.sleep(1)
if __name__ == "__main__":
asyncio.run(main())
在上述代码中,通过 start_times
记录每个任务的开始时间,在循环中不断检查任务是否超时,超时则取消任务。