面试题答案
一键面试1. 资源竞争问题
在高并发场景下,资源竞争通常发生在多个异步任务同时访问和修改共享资源时。
- 解决方案:
- 使用锁机制:在Dart中,可以使用
Lock
类来实现简单的锁机制。当一个异步任务获取到锁后,其他任务必须等待锁被释放才能访问共享资源。 - 隔离共享资源:尽量减少共享资源的使用,将数据按任务或模块进行隔离,避免多个任务同时操作同一数据。
- 使用锁机制:在Dart中,可以使用
- 代码示例:
import 'dart:async';
import 'dart:io';
class Resource {
int data = 0;
}
class ResourceManager {
final _lock = Lock();
final Resource _resource = Resource();
Future<int> readData() async {
await _lock.synchronized(() async {
return _resource.data;
});
}
Future<void> writeData(int value) async {
await _lock.synchronized(() async {
_resource.data = value;
});
}
}
2. 内存泄漏问题
内存泄漏在高并发异步任务中,可能由于任务持有对不再需要的对象的引用,导致垃圾回收器无法回收这些对象。
- 解决方案:
- 及时释放资源:确保在异步任务完成后,及时释放所有不再需要的资源,如关闭网络连接、释放文件句柄等。
- 取消未完成任务:当不再需要某个异步任务时,能够取消它,避免任务继续执行并占用资源。在Flutter中,
Future
可以通过CancelToken
来实现取消操作。
- 代码示例:
import 'dart:async';
import 'package:http/http.dart' as http;
void main() async {
final cancelToken = CancelToken();
try {
final response = await http.get(Uri.parse('https://example.com'),
headers: {'Cancel-Token': cancelToken.token});
print(response.body);
} on IOException catch (e) {
if (e is! CancelException) {
rethrow;
}
}
// 取消任务
cancelToken.cancel();
}
3. 使用Future队列控制并发量
在高并发网络请求场景下,过多的请求可能导致性能问题或服务器过载。通过Future队列可以控制并发请求的数量。
- 解决方案:
- 创建一个
Future
队列,每次从队列中取出一定数量的Future
任务并执行,当有任务完成时,再从队列中取出新的任务执行,以此来控制并发量。
- 创建一个
- 代码示例:
import 'dart:async';
import 'package:http/http.dart' as http;
void main() async {
final requests = List.generate(10, (index) =>
http.get(Uri.parse('https://example.com/$index')));
final maxConcurrent = 3;
final completer = Completer();
var completedCount = 0;
final queue = Queue<Future<http.Response>>.from(requests);
final activeTasks = <Future<http.Response>>[];
void _startNext() {
while (queue.isNotEmpty && activeTasks.length < maxConcurrent) {
final task = queue.removeFirst();
activeTasks.add(task.then((response) {
print('Response from ${response.request?.url}');
return response;
}).whenComplete(() {
activeTasks.remove(task);
completedCount++;
if (completedCount == requests.length) {
completer.complete();
} else {
_startNext();
}
}));
}
}
_startNext();
await completer.future;
}
4. 使用Stream处理异步流数据
Stream可以用于处理一系列异步事件或数据,在高并发场景下,可以通过Stream来处理网络请求的响应流,避免一次性加载大量数据导致的内存问题。
- 解决方案:
- 使用
StreamController
创建一个流,网络请求的响应数据可以通过流来逐步处理,而不是一次性加载到内存中。
- 使用
- 代码示例:
import 'dart:async';
import 'package:http/http.dart' as http;
void main() async {
final controller = StreamController<String>();
final response = await http.get(Uri.parse('https://example.com'));
final stream = response.bodyBytes.asByteStream();
stream.transform(utf8.decoder).listen((data) {
controller.add(data);
}, onDone: () {
controller.close();
});
controller.stream.listen((chunk) {
print('Received chunk: $chunk');
});
}