ios同時スレッドの作成
同時スレッドの作成
メインスレッドはUIインタフェースやユーザインタラクションを扱うのが一般的である.他のことはダウンロード、計算など、別のスレッドで処理するのが一般的です...
まず、3つのスレッドを簡単に作成し、それぞれ1-1000を印刷し、便宜上、スレッド3をメインスレッドに置いて実行します.- (void) firstCounter{
@autoreleasepool {
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"First Counter = %lu", (unsigned long)counter);
}
}
}
- (void) secondCounter{
@autoreleasepool {
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"Second Counter = %lu", (unsigned long)counter);
}
}
}
- (void) thirdCounter{
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"Third Counter = %lu", (unsigned long)counter);
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[NSThread detachNewThreadSelector:@selector(firstCounter)
toTarget:self
withObject:nil];
[NSThread detachNewThreadSelector:@selector(secondCounter)
toTarget:self
withObject:nil];
/* Run this on the main thread */
[self thirdCounter];
}
thirdCounter関数は個々のスレッドで実行されないため、自動リリースプール(autorelease pool)は必要ありません.この方法はアプリケーションのメインスレッドで実行され、各Cocoa Touchプログラムは自動的にメインスレッドに自動リリースプールを作成します.コードの最後にdetachNewThreadSelectorを呼び出すことで、1番目のカウンタと2番目のカウンタを独立したスレッドで実行します.プログラムを実行すると、コンソールウィンドウに次の情報が表示されます.Second Counter=921 Third Counter=301 Second Counter=922 Second Counter=923 Second Counter=924 First Counter=956 Second Counter=925 Counter=957 Second Counter=926 First Counter=958 Third Counter=302 Second Counter=927 Third Counter=303 Second Counter=928
この3つのタイマは同時に動作し,出力された内容はランダムに交互に行われていることがわかる.各スレッドはautorelease poolを作成する必要があります.autorelease poolがreleaseされるまで、autorelease poolはautoreleasedされたオブジェクトの参照を保持します.参照カウントメモリ管理環境では、Cocoa Touchのオブジェクトがautoreleasedされるなど、非常に重要なメカニズムです.オブジェクトインスタンスが作成されると、オブジェクトの参照カウントは1になりますが、作成されたautorelease poolオブジェクトがreleaseされると、autoreleaseのオブジェクトもreleaseメッセージを送信します.この場合、その参照カウントが1の場合、オブジェクトは破棄されます.各スレッドは、スレッドが最初に作成されたオブジェクトとしてautorelease poolを作成する必要があります.そうしないと、そうしないと、スレッドが終了すると、スレッドに割り当てられたオブジェクトにメモリが漏洩します.よりよく理解するために、次のコードを見てみましょう.- (void) autoreleaseThread:(id)paramSender{
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [mainBundle pathForResource:@"AnImage"
ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
/* Do something with the image */
NSLog(@"Image = %@", image);
}
- (void)viewDidLoad {
[super viewDidLoad];
[NSThread detachNewThreadSelector:@selector(autoreleaseThread:)
toTarget:self
withObject:self];
}
このコードを実行すると、コンソールウィンドウにこのような出力情報が表示されます.
*** __NSAutoreleaseNoPool(): Object 0x5b2c990 of class NSCFString autoreleased with no pool in place - just leaking *** __NSAutoreleaseNoPool(): Object 0x5b2ca30 of class NSPathStore2 autoreleased with no pool in place - just leaking *** __NSAutoreleaseNoPool(): Object 0x5b205c0 of class NSPathStore2 autoreleased with no pool in place - just leaking *** __NSAutoreleaseNoPool(): Object 0x5b2d650 of class UIImage autoreleased with no pool in place - just leaking
上記の情報は、作成したautoreleaseのUIImageインスタンスがメモリ漏洩を生成し、FilePathや他のオブジェクトも漏洩を生成したことを示しています.これは、私たちのスレッドでは、開始時にautorelease poolを作成および初期化していないためです.次は正しいコードです.メモリの漏洩がないことを確認するためにテストしてください.- (void) autoreleaseThread:(id)paramSender{
@autoreleasepool {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [mainBundle pathForResource:@"AnImage"
ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
/* Do something with the image */
NSLog(@"Image = %@", image);
}
}
- (void) firstCounter{
@autoreleasepool {
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"First Counter = %lu", (unsigned long)counter);
}
}
}
- (void) secondCounter{
@autoreleasepool {
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"Second Counter = %lu", (unsigned long)counter);
}
}
}
- (void) thirdCounter{
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"Third Counter = %lu", (unsigned long)counter);
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[NSThread detachNewThreadSelector:@selector(firstCounter)
toTarget:self
withObject:nil];
[NSThread detachNewThreadSelector:@selector(secondCounter)
toTarget:self
withObject:nil];
/* Run this on the main thread */
[self thirdCounter];
}
- (void) autoreleaseThread:(id)paramSender{
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [mainBundle pathForResource:@"AnImage"
ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
/* Do something with the image */
NSLog(@"Image = %@", image);
}
- (void)viewDidLoad {
[super viewDidLoad];
[NSThread detachNewThreadSelector:@selector(autoreleaseThread:)
toTarget:self
withObject:self];
}
- (void) autoreleaseThread:(id)paramSender{
@autoreleasepool {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [mainBundle pathForResource:@"AnImage"
ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
/* Do something with the image */
NSLog(@"Image = %@", image);
}
}