長い間、非同期はバックグラウンドスレッドで何かを実行することと同義であると考えていましたが、同期はメインスレッド(UIの更新と対話をブロックする)を意味していました。高価なアクションのためにメインスレッドで実行しないのは、メインスレッドが占有されているときにUIアクションを実行できないためですが、同期が面倒なのはなぜですか?
ただし、メインスレッドで非同期呼び出しを行い、バックグラウンドスレッドで同期呼び出しを行うことができることに気付きました。
ユーザーのUIをブロックするため、高価な呼び出しを同期的にまたはメインスレッドで使用しないようにと言う人が常にいます。これらの2つの個別の問題は、私がしないことを確認する必要がありますか?違いは何ですか?
同期的に何かを呼び出す場合、その操作を開始したスレッドは、タスクが完了するのを待ってから続行することを意味します。非同期とは、待機しないことを意味します。
とはいえ、低速または高価なプロセスを非同期に実行することを人々が提案する場合、非同期で実行するだけでなく、バックグラウンドスレッドで実行することを暗黙的に示唆しています。目標は、メインスレッドを解放して、ユーザーインターフェイスに(フリーズするのではなく)応答し続けることができるようにすることです。そのため、バックグラウンドスレッドに非同期でタスクをディスパッチします。
そのため、2つの部分があります。まず、GCDを例として使用して、バックグラウンドキューを取得します(グローバルバックグラウンドキューのいずれかを取得するか、独自のキューを作成します)。
// one of the global concurrent background queues
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// or you could create your own serial background queue:
//
// dispatch_queue_t queue = dispatch_queue_create("com.domain.app.queuename", 0);
次に、タスクを非同期的にそのキューにディスパッチします。
dispatch_async(queue, ^{
// the slow stuff to be done in the background
});
操作キューのパターンは非常に似ています。操作キューを作成し、そのキューに操作を追加します。
実際には、同期と非同期の区別は、メインキューとバックグラウンドキューの区別とはまったく異なります。しかし、人々が「いくつかの遅いプロセスを非同期的に実行する」という話をするとき、彼らは本当に「遅いプロセスをバックグラウンドキューで非同期的に実行する」と言っています。
"Synchronous"は、本質的に"in order。"を意味します。基本的に、同期操作を行う場合、後から来るものはすべて、操作が開始する前に完了するまで待機する必要があります。
逆に"asynchronous"多かれ少なかれ"not in order。"何かを非同期で行うと、次のコードがすぐに実行され、非同期操作が実行される場合があります…いつか。別のスレッドの残りのコードと並行して実行される場合があります。同じスレッドで別の時間に単純にスケジュールすることもできます。
同期性の概念は、特定のスレッド自体とは関係ありません。操作が完了するまで待つ必要があるかどうかだけです。
メインスレッドが大きな意味でこれに入るのは、Cocoa(Touch)プログラムです。 AppKitはメインスレッドでメインイベントループを実行するため、メインスレッドが操作の完了を待機している場合、入力を処理したりUIを更新したりすることはできません。ただし、バックグラウンドスレッドでコードの一部を実行している場合、同期コードの実行メインイベントループをブロックしません。同期操作の完了を待機しているのはメインスレッドではないためです。
同様に、メインスレッドcanに配置したバックグラウンドスレッドからの長時間実行の非同期操作は、バックグラウンドスレッドが操作の完了を待たずに、まだ問題があるため、問題を引き起こします。イベントループを実行する必要があるメインスレッドで時間を消費します。
簡単な例をいくつか見てみましょう。
マルチスレッドでの非同期呼び出し:
//メソッドは異なるスレッドで呼び出され、現在のスレッドをブロックしません。 [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler: ^(NSURLResponse * response、NSData * data、NSError * error){ }];
マルチスレッドを使用した同期呼び出し:
//ここで、//何かをする//他の何かをする、// //他の何かを別のスレッドで行う場合でも、//他のことを連続して行う。
通常、人々が異なるスレッドを使用する場合、全体の目的は、待機せずに何かを実行できるようにすることです。大量のデータをダウンロードしたいが、UIをスムーズに保ちたいとします。
したがって、dispatch_syncはほとんど使用されません。しかし、それはそこにあります。私は個人的にそれを使ったことはありません。 dispatch_syncを使用するサンプルコードまたはプロジェクトを要求しないのはなぜですか。
1つのスレッドでの非同期呼び出し:
[self performSelector:@selector(doSomething)withObject:nil afterDelay:0];
ここでは、「doSomething」が呼び出される前に完了する現在のランループ。つまり、「doSomething」が呼び出される前に、現在の呼び出しスタックを完了することができます(現在のメソッドが戻る)。
1つのスレッドでの同期呼び出し:
[self doSomething];
これについて説明する必要はないと思います。
一般に、非同期アクティビティはスレッド化と同じではありませんが、iOSではこの方法を使用して実装されます。すべての言語に当てはまるわけではありません。通常、実行ループを使用してさまざまな非同期タスクを管理します。
Swift 3、4、4,2Synchronousは、その操作を開始したスレッドが待機することを意味します続行する前にタスクが完了するようにします。
DispatchQueue.main.sync {
}
Asynchronousは、タスクをバックグラウンドで完了し、完了時にユーザーに通知できることを意味します。
DispatchQueue.main.async {
}
非同期はアウトオブライン、同期はインラインを意味します。同期タスクを実行し、複数のスレッドを一度にブロックできます。
バックグラウンドスレッドにいて、ユーザーインターフェイスの束全体を更新する場合は、dispatch
キューのメインスレッドを呼び出します。 dispatch_sync
を呼び出すと、現在のコードはdispatch
が完了するまで待機するため、現在のバックグラウンドスレッドがブロックされ、メインスレッドの更新中にUIがブロックされます。
ただし、dispatch_async
を呼び出した場合、バックグラウンドスレッドはリストされている残りのコードを続行し、メインスレッドは要求されたdispatch
ブロックを実行します。
メインスレッドの場合も同じことが言えます。メインスレッドからdispatch_sync
をグローバルキューまたはカスタムキューに呼び出すと、メインスレッドはブロックされますが、別のスレッドでコードを実行します。私はそれが使用されるケースを知っていると言うことはできませんが、それは確かに可能です。
計算コード、Webサービスコード、フェッチコードなど、UIに影響を与えないものがある場合は、常に別のスレッドで実行することをお勧めします。この種のものについては、グローバルスレッドにdispatch_async
を実行します。次に、そのコードが完了したら、dispatch_async
をメインスレッドに実行して、計算したものでUIを更新するように指示します。
同期とはブロックを意味し、非同期とは、現在実行していることをブロックせずに後で(おそらく今)完了することを意味します。
この議論はほとんど答えています: 非同期vsマルチスレッド-違いはありますか?
一般的な場合、非同期呼び出しは必ずしも新しいスレッドを作成するとは限りません。これは、既存のスレッドプールまたは外部プロセスを別の方法で実装する1つの方法です。言語、オブジェクトモデル(存在する場合)、および実行時環境に大きく依存します。
非同期とは、呼び出し側スレッドが応答を待機せず、呼び出し側スレッドで非同期アクティビティが発生しないことを意味します。
したがって、基本的に、何かがロードされるのを待っている間に他のアクティビティが発生する可能性がありますが、別のスレッドで実行される場合とされない場合があります。