NSThreadチュートリアル
11173 ワード
1.NSThreadの基本使用
NSThreadオブジェクトはスレッドを表します
threadを実行したタスクはこのthreadを破棄しなかった.
threadを実行したタスクはこのthreadを破棄しなかった.
2.スレッドの状態
注意:スレッドが停止(死亡)すると、タスクを再開できません.
スレッドはブロック状態に入ります(スケジューラ可能なスレッドプールを離れ、スレッドは破棄されずメモリに残っています).
3.スレッドセキュリティ
@synchronized(self){//スレッド同期反発ロックオブジェクトは、スレッドのセキュリティを保証するために一意の反発ロックを必要とします
同じ反発ロックを使用してスレッドの安全を保証
スレッド同期テクノロジーを使用しない反発ロックデータの乱れを使用しない
4.スレッド間通信
サブスレッドに画像を表示
サブスレッドとメインスレッドのデータ通信:サブスレッドダウンロードピクチャダウンロードピクチャダウンロードしてダウンロードしたピクチャをメインスレッドに転送しimageViewに表示する
別のスレッド間の通信方式
5.GCDスレッド間通信
ZYXThread.h
#import
@interface ZYXThread : NSThread
@end
ZYXThread.m
#import "ZYXThread.h"
@implementation ZYXThread
- (void)dealloc
{
NSLog(@"ZYXThread -- dealloc");
}
@end
ViewController.h
#import
@interface ViewController : UIViewController
@end
ViewController.m
#import "ViewController.h"
#import "ZYXThread.h"
@implementation ViewController
- (void)run:(NSString *)param{
for (NSInteger i = 0; i<3; i++) {
NSLog(@"run-----%@-----%@", param, [NSThread currentThread]);
}
}
- (void)createThread1{
//
//NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"jack"];
//
//[thread start];
// 、 , thread self run
ZYXThread *thread = [[ZYXThread alloc] initWithTarget:self selector:@selector(run:) object:@"jack"];
thread.name = @"zyx-thread-1";//
[thread start];//
}
// run-----jack-----{number = 2, name = zyx-thread-1}
// run-----jack-----{number = 2, name = zyx-thread-1}
// run-----jack-----{number = 2, name = zyx-thread-1}
//2016-08-09 11:09:10.659 NSThread[25371:417117] ZYXThread -- dealloc
@end
NSThreadオブジェクトはスレッドを表します
- (void)run2:(NSString *)param{
NSLog(@"run2-----%@-----%@", param, [NSThread currentThread]);
}
- (void)createThread2{
//detach
[ZYXThread detachNewThreadSelector:@selector(run2:) toTarget:self withObject:@"rose"];
}
// run2-----rose-----{number = 2, name = (null)}
// run2-----rose-----{number = 3, name = (null)}
// run2-----rose-----{number = 4, name = (null)}
// run2-----rose-----{number = 5, name = (null)}
// run2-----rose-----{number = 6, name = (null)}
// run2-----rose-----{number = 7, name = (null)}
// run2-----rose-----{number = 8, name = (null)}
// run2-----rose-----{number = 9, name = (null)}
// run2-----rose-----{number = 10, name = (null)}
// run2-----rose-----{number = 11, name = (null)}
// run2-----rose-----{number = 12, name = (null)}
// run2-----rose-----{number = 13, name = (null)}
threadを実行したタスクはこのthreadを破棄しなかった.
- (void)run3:(NSString *)param{
NSLog(@"run3-----%@-----%@", param, [NSThread currentThread]);
}
- (void)createThread3{
[self performSelectorInBackground:@selector(run3:) withObject:@"bill"];
}
// run3-----bill-----{number = 2, name = (null)}
// run3-----bill-----{number = 3, name = (null)}
// run3-----bill-----{number = 4, name = (null)}
// run3-----bill-----{number = 5, name = (null)}
// run3-----bill-----{number = 6, name = (null)}
// run3-----bill-----{number = 7, name = (null)}
// run3-----bill-----{number = 8, name = (null)}
// run3-----bill-----{number = 9, name = (null)}
// run3-----bill-----{number = 10, name = (null)}
// run3-----bill-----{number = 11, name = (null)}
// run3-----bill-----{number = 12, name = (null)}
// run3-----bill-----{number = 13, name = (null)}
// run3-----bill-----{number = 14, name = (null)}
// run3-----bill-----{number = 15, name = (null)}
// run3-----bill-----{number = 16, name = (null)}
// run3-----bill-----{number = 17, name = (null)}
threadを実行したタスクはこのthreadを破棄しなかった.
2.スレッドの状態
- (void)run{
for (NSInteger i = 0; i<10; i++) {
NSLog(@"run-----%zd", i);
if (i == 4) {
[NSThread exit]; // ( )
}
}
}
- (void)createThread {
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
}
// run-----0
// run-----1
// run-----2
// run-----3
// run-----4
注意:スレッドが停止(死亡)すると、タスクを再開できません.
- (void)run2{
NSLog(@"%@",[NSDate date]);
// ( )
[NSThread sleepForTimeInterval:2]; // 2 ( 2 )
NSLog(@"%@",[NSDate date]);
//[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
//[NSThread sleepUntilDate:[NSDate distantFuture]];
}
// 2016-08-09 05:36:01 +0000
// 2016-08-09 05:36:03 +0000
スレッドはブロック状態に入ります(スケジューラ可能なスレッドプールを離れ、スレッドは破棄されずメモリに残っています).
3.スレッドセキュリティ
@interface ViewController ()
/** 01 */
@property (nonatomic, strong) ZYXThread *thread01;
/** 02 */
@property (nonatomic, strong) ZYXThread *thread02;
/** 03 */
@property (nonatomic, strong) ZYXThread *thread03;
/** */
@property (nonatomic, assign) NSInteger ticketCount;
@end
@implementation ViewController
- (void)saleTicket{
while (1) {
@synchronized(self) { //
NSInteger count = self.ticketCount;
if (count > 0) {
self.ticketCount = count - 1;
NSLog(@" %@ , %zd ", [ZYXThread currentThread].name, self.ticketCount);
} else {
NSLog(@" %@ ",[ZYXThread currentThread].name);
break;
}
}
}
}
- (void)start{
self.ticketCount = 10;
self.thread01 = [[ZYXThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread01.name = @" 01";
self.thread02 = [[ZYXThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread02.name = @" 02";
self.thread03 = [[ZYXThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread03.name = @" 03";
[self.thread01 start];
[self.thread02 start];
[self.thread03 start];
}
@end
// 01 , 9
// 02 , 8
// 03 , 7
// 01 , 6
// 02 , 5
// 03 , 4
// 01 , 3
// 02 , 2
// 03 , 1
// 01 , 0
// 02
// 03
// 01
@synchronized(self){//スレッド同期反発ロックオブジェクトは、スレッドのセキュリティを保証するために一意の反発ロックを必要とします
/** */
@property (nonatomic, strong) NSObject *locker;
- (void)start{
self.locker = [[NSObject alloc] init];
- (void)saleTicket{
while (1) {
//@synchronized(self) { //
@synchronized(self.locker){
// 01 , 9
// 02 , 8
// 03 , 7
// 01 , 6
// 02 , 5
// 03 , 4
// 01 , 3
// 02 , 2
// 03 , 1
// 01 , 0
// 02
// 03
// 01
同じ反発ロックを使用してスレッドの安全を保証
- (void)saleTicket{
while (1) {
//@synchronized(self) { //
//@synchronized(self.locker){
NSInteger count = self.ticketCount;
if (count > 0) {
self.ticketCount = count - 1;
NSLog(@" %@ , %zd ", [ZYXThread currentThread].name, self.ticketCount);
} else {
NSLog(@" %@ ",[ZYXThread currentThread].name);
break;
}
//}
}
}
// 01 , 8
// 02 , 8
// 03 , 7
// 01 , 6
// 02 , 5
// 03 , 4
// 01 , 3
// 02 , 2
// 03 , 1
// 01 , 0
// 02
// 03
// 01
スレッド同期テクノロジーを使用しない反発ロックデータの乱れを使用しない
4.スレッド間通信
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
- (void)download{
NSString *imgUrlStr = @"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg";
NSURL *url = [NSURL URLWithString:imgUrlStr];
NSDate *begin = [NSDate date];
NSData *data = [NSData dataWithContentsOfURL:url]; //
NSDate *end = [NSDate date];
NSLog(@"%f", [end timeIntervalSinceDate:begin]);
self.imageView.image = [UIImage imageWithData:data];
}
- (void)way{
[self performSelectorInBackground:@selector(download) withObject:nil];
}
// 3.728395
CFTimeInterval begin = CFAbsoluteTimeGetCurrent();
NSData *data = [NSData dataWithContentsOfURL:url];
CFTimeInterval end = CFAbsoluteTimeGetCurrent();
サブスレッドに画像を表示
- (void)download3{
NSString *imgUrlStr = @"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg";
NSURL *url = [NSURL URLWithString:imgUrlStr];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data]; //
//
/*
[self.imageView performSelector:@selector(setImage:)
onThread:[NSThread mainThread]
withObject:image
waitUntilDone:NO];
[self.imageView performSelectorOnMainThread:@selector(setImage:)
withObject:image
waitUntilDone:NO];
*/
[self performSelectorOnMainThread:@selector(showImage:)
withObject:image
waitUntilDone:YES];
}
- (void)showImage:(UIImage *)image{
self.imageView.image = image;
}
- (void)way3{
[self performSelectorInBackground:@selector(download3) withObject:nil];
}
サブスレッドとメインスレッドのデータ通信:サブスレッドダウンロードピクチャダウンロードピクチャダウンロードしてダウンロードしたピクチャをメインスレッドに転送しimageViewに表示する
別のスレッド間の通信方式
NSPort
NSMessagePort
NSMachPort
5.GCDスレッド間通信
- (void)loadImage {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *imgUrlStr = @"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg";
NSURL *url = [NSURL URLWithString:imgUrlStr];
NSData *data = [NSData dataWithContentsOfURL:url]; //
UIImage *image = [UIImage imageWithData:data]; //
//
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
});
}