NSThreadチュートリアル

11173 ワード

1.NSThreadの基本使用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;
        });
    });
}