iso機制和異步編程
author:andy
isolate機制
? Dart是基于單線程模型的語言。但是在開發(fā)當中我們經(jīng)常會進行耗時操作比如網(wǎng)絡(luò)請求,這種耗時操作會堵塞我們的代碼,所以在Dart也有并發(fā)機制,名叫isolate。APP的啟動入口main函數(shù)就是一個類似Android主線程的一個主isolate。和Java的Thread不同的是,Dart中的isolate無法共享內(nèi)存。
android--主線程,子線程
dart--主isolate,子isolate
疑問
1.java通過子線程執(zhí)行耗時操作,那么dart語言沒有子線程,如何執(zhí)行耗時的操作
import 'dart:isolate';
void main() {
Isolate.spawn(entryPoint, "dahai isolate");
print(‘主isolate打印的。。?!?;
}
void entryPoint(String msg) {
print(msg);
}
疑問
2.上面打印的k會打印成什么?
import 'dart:isolate';
int k;
void main() {
k = 10;
Isolate.spawn(entryPoint, "dahai isolate");
}
void entryPoint(String msg) {
print(k);
}
疑問
3.主isolate和子isolate如何實現(xiàn)數(shù)據(jù)交互
void main() {
//主isolate 接收器
ReceivePort receivePort = new ReceivePort();
//把主接收器的發(fā)送器,傳送給子isolate
Isolate.spawn(entryPoint, receivePort.sendPort);
//主isolate接收的信息打印
receivePort.listen((data) {
print(data);
});
}
void entryPoint(SendPort sendPort) {
sendPort.send('我是來自于子isolate線程');
}
[圖片上傳失敗...(image-b747c2-1600608831069)]
isolate機制跟Android 的handler機制十分相似,都是使用隊列循環(huán)讀取,那么有啥差別呢?
void main() {
ReceivePort receivePort = ReceivePort();
receivePort.sendPort.send('任務(wù)隊列1');
receivePort.sendPort.send('任務(wù)隊列2');
receivePort.sendPort.send('任務(wù)隊列3');
Future.microtask(() {
print('微任務(wù)1');
});
Future.microtask(() {
print('微任務(wù)1');
});
Future.microtask(() {
print('微任務(wù)1');
});
receivePort.listen((t) {
print(t);
});
}
同Android Handler類似,在Dart運行環(huán)境中也是靠事件驅(qū)動的,通過event loop不停的從隊列中獲取消息或者事件來驅(qū)動整個應(yīng)用的運行,isolate發(fā)過來的消息就是通過loop處理。但是不同的是在Android中每個線程只有一個Looper所對應(yīng)的MessageQueue,而Dart中有兩個隊列,一個叫做event queue(事件隊列),另一個叫做microtask queue(微任務(wù)隊列)。

? Dart在執(zhí)行完main函數(shù)后,就會由Loop開始執(zhí)行兩個任務(wù)隊列中的Event。首先Loop檢查微服務(wù)隊列,依次執(zhí)行Event,當微服務(wù)隊列執(zhí)行完后,就檢查Event queue隊列依次執(zhí)行,在執(zhí)行Event queue的過程中,沒執(zhí)行完一個Event就再檢查一次微服務(wù)隊列。所以微服務(wù)隊列優(yōu)先級高,可以利用微服務(wù)進行插隊。
我們先來看個例子:
import 'dart:io';
void main() {
new File("abc.txt").readAsString().then((t) {
print(t);
});
while (true) {}
}
疑問:這個方法能夠打印出來嗎?
異步編程(Future 和 async-await)
Future(flutter中重要的一個異常調(diào)用)
? 在 Dart 庫中隨處可見 Future 對象,通常異步函數(shù)返回的對象就是一個 Future。 當一個 future 執(zhí)行完后,他里面的值 就可以使用了,可以使用 then() 來在 future 完成的時候執(zhí)行其他代碼。Future對象其實就代表了在事件隊列中的一個事件的結(jié)果。
組合
then()的返回值同樣是一個future對象,可以利用隊列的原理進行組合異步任務(wù)
import 'dart:io';
void main() {
new File("abc.txt").readAsString().then((t) {
print(t);
return 100;
}).then((t) {
print(t);
});
}
上面的方式是等待執(zhí)行完成讀取文件之后,再執(zhí)行一個新的future。如果我們需要等待一組任務(wù)都執(zhí)行完成再統(tǒng)一處理一些事情,可以通過wait()完成。
import 'dart:io';
void main() {
Future future = new File("abc.txt").readAsString();
Future future2 = Future.delayed(Duration(seconds: 3));
Future.wait([future, future2]).then((values) {
print(values[0]);
print(values[1]);
});
}
async/await
? 使用async和await的代碼是異步的,但是看起來很像同步代碼。當我們需要獲得A的結(jié)果,再執(zhí)行B,時,你需要then()->then(),但是利用async與await能夠非常好的解決回調(diào)地獄的問題:
//async 表示這是一個異步方法,await必須再async方法中使用
//異步方法只能返回 void和Future
import 'dart:io';
void main() {
readNet().then((t) {
print(t);
});
}
Future<String> readNet() async {
String str1 = await new File("abc.txt").readAsString();
String str2 = await new File("123.txt").readAsString();
return "$str1 $str2";
}