IOSが合併スレッドを作成した例を詳しく説明する。
IOSが合併スレッドを作成した例を詳しく説明する。
スレッドを作成
メインスレッドは、一般的にUIインターフェースおよびユーザーインタラクションを処理するものである。他の事は普通は別のスレッドで処理します。ダウンロード、計算などです。
まず簡単に3つのスレッドを作成し、それぞれ1万1,000をプリントアウトします。便宜上、スレッド3はメインスレッドに置いて実行します。
アクティブにして、メインスレッドに自動リリースプールを作成します。
コードの最後にdetachNewThreadSelectorを呼び出して、最初のカウンタと二つ目のカウンタを独立したスレッドで実行します。今プログラムを実行すれば、コンソールの窓口で以下の情報が見られます。
各スレッドは、最初に作成されたオブジェクトとしてautrelease poolを作成する必要があります。そうしないと、スレッドが終了すると、スレッドに割り当てられたオブジェクトがメモリ漏れを起こします。より良い理解のために、下記のコードを見に来ました。
スレッドを作成
メインスレッドは、一般的にUIインターフェースおよびユーザーインタラクションを処理するものである。他の事は普通は別のスレッドで処理します。ダウンロード、計算などです。
まず簡単に3つのスレッドを作成し、それぞれ1万1,000をプリントアウトします。便宜上、スレッド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関数は、単独のスレッド内で動作していないので、自動リリースプール(autrelease pool)は必要ありません。この方法はアプリケーションのメインスレッドで実行されます。各Cocoa Touchプログラムは自動的に実行されます。アクティブにして、メインスレッドに自動リリースプールを作成します。
コードの最後にdetachNewThreadSelectorを呼び出して、最初のカウンタと二つ目のカウンタを独立したスレッドで実行します。今プログラムを実行すれば、コンソールの窓口で以下の情報が見られます。
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つのタイマーは同時に動作し、出力内容はランダムに交互になっていることが分かります。各スレッドはautrelease poolを作成しなければなりません。autrelease poolがreleaseされる前に、autrelease poolはautreleasedの対象となる引用を持っています。参照カウントメモリ管理環境においては、これはCocoa Touchにおけるオブジェクトがautreleasedされるような非常に重要な機構である。いずれにしても、オブジェクトのインスタンスを作成する場合、オブジェクトの参照カウントは1であるが、作成されたautrelease poolオブジェクトがreleaseされた場合、autreleaseのオブジェクトも同じであるreleaseメッセージを送信し、この場合、その参照カウントは1であると、オブジェクトは破棄される。 各スレッドは、最初に作成されたオブジェクトとしてautrelease 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
上記の情報は、私たちが作成したautreleaseのUImageの例にメモリリークが発生したことを示しています。また、FilePathと他のオブジェクトにもリークが発生しました。これは私たちのスレッドでは、開始時にautrelease 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);
}
}
以上は、IOSの併発スレッドに関する実例を使っていますが、質問があれば、メッセージを残して討論し、共に進歩し、ありがとうございます。