iosマルチスレッド操作-GCD遅延操作と関連使用方法
6474 ワード
iosマルチスレッド操作-GCD遅延操作と関連使用方法
0x01.iOSバージョン
GCD関数を使用すると、遅延操作が可能です.
次に、パラメータ
このことから、プライマリ・キュー・カラムのスケジューリング・タスクが非同期で実行され、実行キューをグローバル・キューとシリアル・キューに変更すると、結果はまったく同じであり、この関数が非同期操作を実行していることがわかる.GCDには、あるコードがプログラム実行中に1回しか実行されないことを保証する関数があります.この関数は次のとおりです.
ARC環境における単純な一例モード:
2つの方法で印刷されたアドレスはまったく同じです!MRC環境では、次のコードがあります.
0x02.swift 3.0バージョン
1.実行の遅延:
PS.
2.グローバルキューが時間のかかる操作を行った後、メインスレッドに切り替えてUIをリフレッシュする
3.同期実行操作
4.キュー
5.複数のタスクを実行した後、ある操作を行います.
1つまたは複数のタスクの後に別のタスクを実行する場合は、タスク間に待機を追加します.
6. DispatchWorkItemは、タスク・エントリとして理解され、デフォルト値があるため、受信優先度などのパラメータを初期化できます.また、閉パケットは1つだけ入力できます.同様にwaitメソッドもあり、使用は上とあまり差がありません.
7. barrierの参加は、キューに参加する前の「タスク」の実行が完了するまで実行されません.その後、キューの「タスク」に追加すると、この「タスク」の実行が完了するまで実行が開始されません.ここでの「タスク」はDispatchWorkItemで作成されます.
8.信号量
スレッドの安全な統計数のために、信号量をカウントします.初期化メソッドは1つのみで、1つのIntタイプの数が入力されます.
0x01.iOSバージョン
GCD関数を使用すると、遅延操作が可能です.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
次に、パラメータ
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)) : NSEC_PER_SEC
のヘッダファイルでの定義を分解します.#define NSEC_PER_SEC 1000000000ull /* nanoseconds per second */
このパラメータは、これからどのくらいのナノ秒dispatch_get_main_queue():
が経過したかを示し、メインキュー. ^{ }:
がblockタスクを表すことを示します.どのくらいのナノ秒が経過した後、プライマリ・キューによってタスクが非同期で実行されるか、同期で実行されるかをテストできます.コードは次のとおりです.// when
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
void (^task)() = ^ {
//
NSLog(@"%@", [NSThread currentThread]);
};
// ,
dispatch_after(when, dispatch_get_main_queue(), task);
// ,
NSLog(@"come here");
このことから、プライマリ・キュー・カラムのスケジューリング・タスクが非同期で実行され、実行キューをグローバル・キューとシリアル・キューに変更すると、結果はまったく同じであり、この関数が非同期操作を実行していることがわかる.GCDには、あるコードがプログラム実行中に1回しか実行されないことを保証する関数があります.この関数は次のとおりです.
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
})
dispatch_once_t
はヘッダファイルで以下のように定義される:typedef long dispatch_once_t
;このことから、このタイプはlong
タイプであることがわかる.onceToken
が0に等しい場合、block
コードが実行される.dispatch_once
はスレッドが安全で、スレッドの安全に関わる限りロックに関わる.dispatch_once
の内部にもロックがあり、反発ロックよりも性能が高い.この関数を使用して、プログラムの実行中に1つのインスタンスしかなく、外部からアクセスしやすく、インスタンスの個数を制御しやすく、システムリソースを節約することができます.アプリケーションがソースを共有する必要がある場合は、単一のインスタンスモードで実現できます.一例モードはARCとMRCの2つのケースに分けられ,マクロでARC環境であるか否かを判断できる.#if __has_feature(objc_arc)
// ARC
#else
// MRC
#endif
ARC環境における単純な一例モード:
@implementation SoundTools
// ,
static id instance;
// , dispatch_once
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
//
+ (instancetype)sharedSoundTools {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (id)copyWithZone:(NSZone *)zone {
return instance;
}
@end
:
- (void)viewDidLoad {
[super viewDidLoad];
SoundTools *s1 = [SoundTools sharedSoundTools];
NSLog(@"%p", s1);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
SoundTools *s2 = [SoundTools sharedSoundTools];
NSLog(@"%p", s2);
}
2つの方法で印刷されたアドレスはまったく同じです!MRC環境では、次のコードがあります.
// ,
static id instance;
// , dispatch_once
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
//
+ (instancetype)sharedSoundTools {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (id)copyWithZone:(NSZone *)zone {
return instance;
}
#pragma mark - MRC
/**
, , !
*/
// -1
- (oneway void)release {
// , highlight
}
// +1,
- (instancetype)retain {
return instance;
}
// , !
- (instancetype)autorelease {
return instance;
}
//
- (NSUInteger)retainCount {
// :limits.h CPU
return ULONG_MAX;
}
0x02.swift 3.0バージョン
1.実行の遅延:
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+3.0, execute: {
[unowned self] () -> Void in
//
})
PS.
DispatchTime
対象はnow()
で現在時間を取得し、秒数を加えればよい2.グローバルキューが時間のかかる操作を行った後、メインスレッドに切り替えてUIをリフレッシュする
DispatchQueue.global().async {
//
DispatchQueue.main.async {
// UI
}
}
3.同期実行操作
DispatchQueue.global().sync {
//
}
4.キュー
DispatchQueue
を作成するデフォルトの初期化方法は同期キューを作成し、同時キューを作成する場合はattributesで宣言する.concurrent. //
let serialQueue = DispatchQueue(label: "name")
//
let concurrentQueue = DispatchQueue(label: "name", attributes: .concurrent)
5.複数のタスクを実行した後、ある操作を行います.
DispatchGroup
を使用します.すべての操作が完了した後、notify
を実行します. let group = DispatchGroup()
let queue1 = DispatchQueue(label: "queue1")
queue1.async(group: group) {
// 1
}
let queue2 = DispatchQueue(label: "queue2")
queue1.async(group: group) {
// 2
}
group.notify(queue: DispatchQueue.main) {
//
}
1つまたは複数のタスクの後に別のタスクを実行する場合は、タスク間に待機を追加します.
//
group.wait(timeout: DispatchTime.distantFuture)
6.
DispatchWorkItem
の使用 let queue = DispatchQueue(label: "queue", attributes: .concurrent)
let workItem = DispatchWorkItem {
//
}
queue.async(execute: workItem)
print("before waiting")
workItem.wait()
print("after waiting")
7.
barrier
柵 let barrierWorkItem = DispatchWorkItem(flags: .barrier) {
// , “ ” , “ ”
}
let queue = DispatchQueue(label: "queue", attributes: .concurrent)
queue.async(execute: barrierWorkItem)
8.信号量
スレッドの安全な統計数のために、信号量をカウントします.初期化メソッドは1つのみで、1つのIntタイプの数が入力されます.
let semaphore = DispatchSemaphore(value: 10)
//
semaphore.wait()
//
semaphore.signal()