Flutterでの非同期の原理の分析と非同期プログラミングの待機
碑文
-ビットとピースの蓄積から始めて、世界に剣を構え、どこへ行っても、つまり毎日投げるように完璧を目指して努力する必要があります。
** | あなたが必要があるかもしれません |
---|---|
CSDN | NetEase Cloud Classroomチュートリアル |
ナゲット | EDU Academyチュートリアル |
ほとんど知っている | Flutterシリーズの記事 |
非同期プログラミングの使用に関するいくつかの記事を書いた後、Flutter非同期プログラミングの原則を皆さんと共有する時が来ました。
ヘッダー1 | ヘッダー2 |
---|---|
Flutter遅延タスク、FlutterはFutureおよびTimerを通じて遅延タスクを実装します | Flutter非同期プログラミングでのasyncとawaitの基本的な使用法 |
Flutter非同期プログラミングでのasyncとawaitの基本的な使用法 | FlutterがFutureBuilder再描画ソリューションを非同期に読み込みます |
1非同期プログラミングの基本概念
1.1タスクのスケジューリング
最初にタスクスケジューリングについて話しましょう。ほとんどのオペレーティングシステム(WindowsやLinuxなど)のタスクスケジューリングは、タイムスライスローテーションを使用するプリエンプティブスケジューリング方式です。シングルコアCPUの場合、2つのタスクが並行して実行されますが、CPUが実際に実行しています。 220V ACライトディスプレイの原理と同じように、ユーザーは高速切り替えで切り替えの一時停止を感じません。つまり、タスクが短時間実行された後、強制的に一時停止して次のタスクを実行し、各タスクが順番に実行されます。
タスク実行中の短い時間をタイムスライスといいます。タスク実行中の状態を実行状態といいます。一定時間実行すると強制的に一時停止して次のタスクを実行します。サスペンド中のタスクは準備完了状態で、それに属する次のタイムスライスを待ちます到着すると、タスクの停止と実行の切り替えをタスクスケジューリングと呼びます。
1.2プロセス
コンピューターのコアはすべての計算タスクを実行するCPUであり、オペレーティングシステムはコンピューターのマネージャーです。タスクのスケジューリング、リソースの割り当て、および管理を担当します。オペレーティングシステムでは複数のプロセスが実行されており、各プロセスはデータセット上の特定の独立した機能プログラムの動的実行プロセスは、アプリケーションプログラムのキャリアです。
オペレーティングシステムは、プロセスを単位として、システムリソース(CPUタイムスライス、メモリ、その他のリソース)を割り当てます。プロセスは、リソース割り当ての最小単位、つまりオペレーティングシステムの最小単位です。
1.3スレッド
スレッドはプロセスの概念であり、プロセスには複数のスレッドを含めることができます。
タスクスケジューリングは、タイムスライスローテーションのプリエンプティブスケジューリング方式を使用しており、プロセスはタスクスケジューリングの最小単位です。
デフォルトでは、プロセスには通常1つのスレッドしかなく、プロセス自体はスレッドであるため、スレッドは軽量プロセスと呼ばれます。
1.4コルーチン
コルーチンは、スレッドベースですが、スレッドよりも軽量な存在です。これは、スレッドの概念です。1つのスレッドに複数のコルーチンを含めることができます。
従来のJ2EEシステムでは、各要求がスレッドを占有して、完全なビジネスロジック(トランザクションを含む)を完了します。したがって、システムのスループットは、各スレッドの時間のかかる操作に依存します。時間のかかるI / O動作が発生した場合、この時点でスレッドがブロックされているため、システム全体のスループットはすぐに低下します。スレッドが多数ある場合、他の多くのスレッドが待機およびアイドル状態になります(前のスレッドを待機しています)。スレッドは実行後にのみ実行できるため、不完全なリソースアプリケーションになります。
最も一般的な例は、同期ブロッキングJDBCです。接続プロセス中、スレッドはCPUをまったく使用せずに計算を行いますが、待機状態にあります。また、スレッドが多すぎると、ContextSwitch(コンテキストスイッチ)オーバーヘッドも増加します。 。
長期間のI / O操作がある場合のコルーチンの出現。現在占有されているタスクチャネルを放棄し、次のタスクを実行し、スレッドにスケジューリングを実装し、ContextSwitchのオーバーヘッドを排除して、カーネルに入るのを回避します。コンテキスト切り替えのレベルが原因でパフォーマンスが低下したため、IO上のスレッドのパフォーマンスボトルネックが解消されました。プログラミングの観点から見ると、コルーチンのアイデアは本質的に、制御フローのアクティブなyieldおよびresumeメカニズムです。
2 Flutterプロジェクトでの非同期プログラミングの原則
たとえば、Flutterによって開発されたAPPが携帯電話にインストールされています。APPアイコンをクリックして開始すると、モバイルオペレーティングシステムが現在のAPPのプロセスを作成し、Flutterプロジェクトでメイン関数を介してFlutterによってビルドされたプロジェクトを開始します。
Dartはシングルスレッドモデルに基づいた言語であるため、Flutterでの一般的な非同期操作は、実際にはシングルスレッドのスケジューリングタスクを通じて実装されます。
Dartのスレッドメカニズムは分離と呼ばれます。Flutterプロジェクトでは、実行中のFlutterプログラムは1つ以上の分離で構成されます。デフォルトで開始されるFlutterプロジェクトは、メイン機能によって開始され、主分離を作成します。フォローアップは分離の開発と使用について説明する特別な記事があり、主な分離はFlutterのメインスレッド、つまりUIスレッドです。
2.1 Dartイベントループ
シングルスレッドモデルは、主にイベントループ(イベントループ)と2つのキュー(イベントキューとマイクロタスクキュー)を維持します。
Flutterプロジェクトプログラムがクリックイベント、IOイベント、ネットワークイベントなどをトリガーすると、それらはeventLoopに追加されます。eventLoopは常にループ内にあります。メインスレッドがイベントキューが空でないことを検出すると、イベントを取り出して実行します。 。
マイクロタスクキューは現在のアイソレート内のタスクのみを処理し、イベントキューよりも優先度が高くなります。空港のVIP待合室と同様に、VIPユーザーは常に最初に飛行機に搭乗してから、パブリックキューの入り口を開きます。イベントキューの場合マイクロタスクを挿入します。現在のイベントが実行されると、マイクロタスクイベントをキューに挿入できます。マイクロタスクキューの存在は、Dartにタスクキューのソリューションを提供します。
イベントループがマイクロタスクイベントを処理しているとき、イベントキューはブロックされます。現時点では、アプリはUIを描画できず、マウスイベントやI / Oなどのイベントに応答できません。
これら2つのタスクキューでのタスクの切り替えは、コルーチンのスケジューリングメカニズムと同等です。
2.2将来の概要
Futureはイベントです。awaitでマークされたすべてのハンドルもイベントです。タイマーによって作成されたタスクもイベントです。Futureが作成されるたびに、イベントキューにスローされます。
asyncとawaitの組み合わせを使用して、イベントをイベントキューに挿入し、非同期操作を実装できます。
Futureの主な機能は、チェーン呼び出しメソッドと、非同期タスクを処理するためのメソッドの完全なセットを提供することです。
2.3 Futureの一般的な方法の概要
Flutterは次の3つのメソッドを提供します。コールバックを登録して、Future非同期情報の処理結果を監視します。
//处理完成时候的回调,一般都是成功回调
Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
//处理失败的回调,比如throw一个error就会走到这里
Future<T> catchError(Function onError, {bool test(Object error)});
//Future.whenComplete总是在Future完成后调用,不管Future的结果是正确的还是错误的。
Future<T> whenComplete(FutureOr action());
基本的な未来を創る未来の構築法
var f1 = Future(() {
print("1111");
});
print("33233");
//33233
//1111
指定された戻り値でFutureを作成します
Future.value("Success").then((value) => (print('测试$value')));
実行を遅らせて未来を作る
//延迟三秒执行
Future.delayed(Duration(seconds: 3), () {
print("future delayed");
});
特定のセットに従って、一連の先物を作成し、これらの先物を順番に実行します
Future.forEach([1,2,3], (item) {
return Future.delayed(Duration(seconds: 2),() {
print(item);
});
});
//1
//2
//3
複数の非同期タスクを連続して実行する
var f1 = Future.delayed(Duration(seconds: 1),() => (1));
var f2 = Future.delayed(Duration(seconds: 2),() => (2));
var f3 = Future.delayed(Duration(seconds: 3),() => (3));
Future.wait([f1,f2,f3]).then((value) => print(value)).catchError(print);
上記で作成された非同期タスクは、イベントキューに追加されたすべてのタスクであり、マイクロタスクキューで実行されるフューチャーを作成します。マイクロタスクキューの優先度は、イベントキューよりも高くなっています。
Future(() => (print(11111)));
Future(() => (print(22222)));
Future.microtask(() => (print(33333)));