一文詳解Dart如何實(shí)現(xiàn)多任務(wù)并行
Isolate(隔離區(qū)域)
Dart 是一種支持多任務(wù)并行的編程語言,它提供了多種機(jī)制來實(shí)現(xiàn)并發(fā)和并行。下面是 Dart 實(shí)現(xiàn)多任務(wù)并行的幾種方式:
Dart 中的 Isolate 是一種輕量級的并發(fā)機(jī)制,類似于線程。每個(gè)隔離區(qū)域都是獨(dú)立的內(nèi)存空間,每個(gè)隔離區(qū)域都有自己的內(nèi)存空間和執(zhí)行線程,因此不同的隔離區(qū)域之間可以獨(dú)立地執(zhí)行代碼,每個(gè)隔離區(qū)都在自己的核心上運(yùn)行,不會(huì)阻塞其他 Isolate。從而實(shí)現(xiàn)并發(fā)。但是有一點(diǎn)需要注意它們之間不能直接共享數(shù)據(jù),必須通過消息傳遞來實(shí)現(xiàn)。
下面是一個(gè)簡單的示例代碼,展示了如何使用Isolate在Dart中實(shí)現(xiàn)并發(fā)執(zhí)行:
import 'dart:isolate';
void main() async {
// 創(chuàng)建兩個(gè)隔離區(qū)域
final isolate1 = await Isolate.spawn(runIsolate, 1);
final isolate2 = await Isolate.spawn(runIsolate, 2);
// 等待隔離區(qū)域執(zhí)行完畢
await Future.wait([isolate1.exitCode, isolate2.exitCode]);
}
void runIsolate(int id) {
// 隔離區(qū)域中執(zhí)行的代碼
print('Isolate $id is running');
}
在上面的示例中,我們首先使用Isolate.spawn函數(shù)創(chuàng)建兩個(gè)隔離區(qū)域,每個(gè)隔離區(qū)域都會(huì)執(zhí)行runIsolate函數(shù),并傳入不同的參數(shù)(1和2)。runIsolate函數(shù)是隔離區(qū)域中實(shí)際執(zhí)行的代碼,它只是簡單地打印一條信息。
在創(chuàng)建完隔離區(qū)域之后,我們使用Future.wait函數(shù)等待隔離區(qū)域執(zhí)行完畢。這里的exitCode屬性返回隔離區(qū)域的退出代碼,如果代碼成功執(zhí)行,它將返回0。
當(dāng)我們運(yùn)行上面的代碼時(shí),我們會(huì)看到如下輸出:
Isolate 1 is running
Isolate 2 is running
可以看到,兩個(gè)隔離區(qū)域幾乎同時(shí)啟動(dòng)并執(zhí)行,實(shí)現(xiàn)了并發(fā)執(zhí)行的效果。這只是Isolate的簡單示例,您可以使用它來執(zhí)行更復(fù)雜的并發(fā)任務(wù),例如使用多個(gè)Isolate同時(shí)下載多個(gè)文件,或在不同的隔離區(qū)域中執(zhí)行計(jì)算密集型任務(wù),以提高性能等。
async/await
在Dart中,async/await使用的是Future對象來實(shí)現(xiàn)異步操作。當(dāng)我們在一個(gè)函數(shù)或方法前面加上async關(guān)鍵字時(shí),這個(gè)函數(shù)就變成了一個(gè)異步函數(shù)。在異步函數(shù)中使用await關(guān)鍵字可以等待其他異步操作的結(jié)果,而不會(huì)阻塞當(dāng)前函數(shù)的執(zhí)行。
下面是一個(gè)使用async/await實(shí)現(xiàn)異步并發(fā)的Demo代碼,它會(huì)同時(shí)下載兩個(gè)URL的內(nèi)容,并在兩個(gè)下載操作都完成后將結(jié)果打印出來:
import 'dart:async';
import 'dart:convert';
import 'dart:io';
Future<void> main() async {
final url1 = 'https://www.example.com';
final url2 = 'https://www.example.net';
final result1 = downloadUrl(url1);
final result2 = downloadUrl(url2);
final results = await Future.wait([result1, result2]);
for (final result in results) {
print(result);
}
}
Future<String> downloadUrl(String url) async {
final httpClient = HttpClient();
final request = await httpClient.getUrl(Uri.parse(url));
final response = await request.close();
final contents = await response.transform(utf8.decoder).join();
httpClient.close();
return contents;
}
在上面的代碼中,downloadUrl方法是一個(gè)異步函數(shù),它使用HttpClient類下載給定URL的內(nèi)容。在main函數(shù)中,我們使用Future.wait方法來等待兩個(gè)下載操作都完成,然后打印結(jié)果。由于result1和result2是同時(shí)進(jìn)行的,因此整個(gè)過程是并發(fā)的。
Stream
Dart 中的 Stream 是一種基于事件的異步編程模型,它可以處理連續(xù)的異步事件流。使用 Stream 可以將一個(gè)長時(shí)間運(yùn)行的任務(wù)分解成多個(gè)小任務(wù),并且可以在每個(gè)小任務(wù)完成后將結(jié)果推送到事件流中,這樣其他任務(wù)就可以異步地獲取結(jié)果。
下面是一個(gè)使用Stream實(shí)現(xiàn)異步并發(fā)的Demo代碼,它會(huì)從兩個(gè)URL下載數(shù)據(jù)并將結(jié)果打印出來:
import 'dart:async';
import 'dart:convert';
import 'dart:io';
Future<void> main() async {
final url1 = 'https://www.example.com';
final url2 = 'https://www.example.net';
final stream1 = downloadUrl(url1);
final stream2 = downloadUrl(url2);
await for (final result in StreamGroup.merge([stream1, stream2])) {
print(result);
}
}
Stream<String> downloadUrl(String url) async* {
final httpClient = HttpClient();
final request = await httpClient.getUrl(Uri.parse(url));
final response = await request.close();
await for (final chunk in response.transform(utf8.decoder)) {
yield chunk;
}
httpClient.close();
}
在上面的代碼中,downloadUrl方法返回一個(gè)Stream對象,用于異步下載給定URL的內(nèi)容。在main函數(shù)中,我們使用StreamGroup.merge方法將兩個(gè)下載流合并為一個(gè),并使用await for循環(huán)逐個(gè)處理下載結(jié)果。
需要注意的是,在downloadUrl方法中,我們使用yield關(guān)鍵字來逐個(gè)將下載的數(shù)據(jù)塊發(fā)送到Stream中,這樣就可以在下載過程中不斷地將數(shù)據(jù)發(fā)送出去,而不用等到所有數(shù)據(jù)都下載完成后再一次性發(fā)送。這也是Stream在處理大量異步事件時(shí)的優(yōu)勢之一。
Compute Function
Dart 中的 Compute Function 是一種可以在獨(dú)立的 Isolate 中運(yùn)行的函數(shù),它可以接收輸入?yún)?shù)并返回結(jié)果。使用 Compute Function 可以將一個(gè)計(jì)算密集型的任務(wù)分解成多個(gè)小任務(wù),在每個(gè)小任務(wù)中使用 Compute Function 來并行地計(jì)算結(jié)果,最終將結(jié)果合并起來。
下面是一個(gè)使用Compute Function實(shí)現(xiàn)異步并發(fā)的Demo代碼,它會(huì)計(jì)算兩個(gè)斐波那契數(shù)列,并將結(jié)果打印出來:
import 'dart:async';
import 'package:flutter/foundation.dart';
Future<void> main() async {
final result1 = compute(fibonacci, 40);
final result2 = compute(fibonacci, 41);
final results = await Future.wait([result1, result2]);
for (final result in results) {
print(result);
}
}
int fibonacci(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
在上面的代碼中,我們使用compute函數(shù)將斐波那契數(shù)列的計(jì)算任務(wù)交給后臺(tái)隔離線程執(zhí)行,然后使用Future.wait方法等待兩個(gè)任務(wù)都完成后打印結(jié)果。
需要注意的是,在使用compute函數(shù)時(shí),傳遞給它的函數(shù)必須是頂層函數(shù)或靜態(tài)函數(shù),因?yàn)楹笈_(tái)隔離線程無法訪問非靜態(tài)變量或?qū)嵗兞俊?/p>
總的來說,Dart 提供了多種機(jī)制來實(shí)現(xiàn)多任務(wù)并行,包括 Isolate、async/await、Stream 和 Compute Function。這些機(jī)制可以根據(jù)具體的任務(wù)需求選擇使用,從而實(shí)現(xiàn)高效的并發(fā)和并行。
以上就是一文詳解Dart如何實(shí)現(xiàn)多任務(wù)并行的詳細(xì)內(nèi)容,更多關(guān)于Dart 多任務(wù)并行的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
flutter中如何使用和擴(kuò)展ThemeData實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了flutter中如何使用和擴(kuò)展ThemeData實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Flutter SizedBox布局組件Widget使用示例詳解
這篇文章主要為大家介紹了Flutter SizedBox布局組件Widget使用示例詳解2023-02-02
Dart多態(tài)控制反轉(zhuǎn)編碼規(guī)范實(shí)例詳解
這篇文章主要為大家介紹了Dart多態(tài)控制反轉(zhuǎn)編碼規(guī)范實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Dart語法之變量聲明與數(shù)據(jù)類型實(shí)例詳解
這篇文章主要為大家介紹了Dart語法之變量聲明與數(shù)據(jù)類型實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
Android開發(fā)中Dart語言7個(gè)很酷的特點(diǎn)
這篇文章主要為大家介紹了Android開發(fā)中Dart語言7個(gè)很酷的特點(diǎn)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Flutter學(xué)習(xí)筆記(三)RowColum布局
這篇文章主要介紹了Flutter學(xué)習(xí)筆記(三)RowColum布局,通俗來說,就是橫向布局和縱向布局的用法,需要的朋友可以參考下2023-04-04
Dart多個(gè)future隊(duì)列完成加入順序關(guān)系及原子性論證
這篇文章主要介紹了Dart多個(gè)future隊(duì)列完成加入順序關(guān)系及原子性論證,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Flutter 語法進(jìn)階抽象類和接口本質(zhì)區(qū)別詳解
這篇文章主要為大家介紹了Flutter 語法進(jìn)階抽象類和接口本質(zhì)區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

