iOS开发-------多线程的基础使用方法

作者: 西西哈哈 | 来源:发表于2016-11-18 02:54 被阅读38次

实际开发中多线程的使用时非常常见的,多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。

本文介绍关于多线程常用的,也是最基本的使用方法。

1.NSObject自带的多线程

首先创建一个imageView和button:

(文本创建较多按钮暂时用数字后缀代替,实际编程中尽量避免使用数字)

@property(nonatomic, strong)UIImageView *imageView;
@property(nonatomic, strong)UIButton *button2;

初始化imageView和相应的button:
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(107,   
 500, 200, 200)];
 self.imageView.backgroundColor = [UIColor yellowColor];
 [self.view addSubview:self.imageView];

self.button2 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button2.frame = CGRectMake(107, 10 + 40, 200, 30);
self.button2.backgroundColor = [UIColor blueColor];
[self.button2 setTitle:@"自带的多线程" forState:UIControlStateNormal];
[self.button2 addTarget:self action:@selector(didClickedButton2:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button2];

执行方法
//自带的多线程
- (void)didClickedButton2:(UIButton *)button2
{
//在多线程里面执行某个方法
[self performSelectorInBackground:@selector(getImageByURL) withObject:nil];

}
//这个方法会在分支线程里执行(非主线程)
- (void)getImageByURL
{
//1.在分支线程里请求数据
self.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"]];
//2.回到主线程更新UI
[self performSelectorOnMainThread:@selector(updataUI) withObject:nil waitUntilDone:YES];
}

//3.回主线程更新UI方法
- (void)updataUI
{
self.imageView.image = [UIImage imageWithData:self.data];
}
B4BB0391-2459-47BA-A5C2-70546A2CE900.png

点击按钮

72C6AF07-3489-4186-B162-4A77DC560BBF.png

2.自动分配线程

@property(nonatomic, strong)UIButton *button3;

self.button3 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button3.frame = CGRectMake(107, 10 + 40 + 40, 200, 30);
self.button3.backgroundColor = [UIColor blueColor];
[self.button3 setTitle:@"自动分配" forState:UIControlStateNormal];
[self.button3 addTarget:self action:@selector(didClickedButton3:)   forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button3];

//自动分配线程
- (void)didClickedButton3:(UIButton *)button3
{
[NSThread detachNewThreadSelector:@selector(getImageByURL) toTarget:self withObject:nil];

}

点击按钮


B6237B5D-E059-4241-9224-C9316FCD5D0B.png 832A4853-3703-4180-BDC4-B124A98F884B.png

3.手动分配线程

@property(nonatomic, strong)UIButton *button4;

self.button4 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button4.frame = CGRectMake(107, 10 + 40 + 40 + 40, 200, 30);
self.button4.backgroundColor = [UIColor blueColor];
[self.button4 setTitle:@"手动分配" forState:UIControlStateNormal];
[self.button4 addTarget:self action:@selector(didClickedButton4:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button4];

//手动分配线程
- (void)didClickedButton4:(UIButton *)button4
{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(getImageByURL) object:nil];
//手动开启线程
[thread start];
//让线程延迟3秒
[NSThread sleepForTimeInterval:3];
}
6CBED177-5C1E-4019-8923-F81FD9DFDC63.png

点击按钮视图会在3秒后呈现


A02A39DC-B9FD-452C-B1BF-5326EFF8CA70.png

4.NSIncationOperation 方法:

按钮按以上依次创建,这里只写方法
#pragma mark -- NSIncationOperation 方法:
- (void)didClickedButton5:(UIButton *)button5
{
//这个类是NSOperation的一个子类
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(getImageByURL) object:nil];
//手动开启
[invocationOperation start];
}
点击按钮


C53A3D92-9651-4DBD-A222-EA0C032D7811.png

5.NSBlockOperation方法

pragma mark -- NSBlockOperation方法

- (void)didClickedButton6:(UIButton *)button6
{
__weak ViewController *blockVC = self;
//这个类也是NSOperation的一个子类
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
    //在分支线程里请求数据
    blockVC.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"]];
    
    //回主线程更新UI
    [self performSelectorOnMainThread:@selector(updataUI) withObject:nil waitUntilDone:YES];
}];
//手动开启
[blockOperation start];
}

点击按钮

C329C991-E75E-4043-BBE6-3CF1CCB841B1.png

6.线程队列

- (void)didClickedButton7:(UIButton *)button7
{
//创建队列对象
NSOperationQueue *queue = [NSOperationQueue new];
//设置最大并发数
queue.maxConcurrentOperationCount = 1;
//向队列中添加任务
for (NSInteger i = 0; i < 10; i++) {
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"当前线程 : %@ 是否是主线程:%d : %ld",[NSThread currentThread], [NSThread isMainThread], i );
        
    }];
    //将任务添加到线程队列中
    [queue addOperation:blockOperation];
}
}

点击按钮 打印出:


05F7FF13-B5EE-450E-AEDA-D41BC5F5AC1F.png

7.GCD串行

- (void)didClickedButton8:(UIButton *)button8
{
//方法一:

获取程序的主队列:
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
    NSLog(@"我是第一个任务,是否是主线程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第二个任务,是否是主线程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第三个任务,是否是主线程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第四个任务,是否是主线程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第五个任务,是否是主线程:%d",[NSThread isMainThread]);
});


//方法二:
//创建一个串行队列
//参数一:队列的名字(苹果推荐以反域名的形式书写)
//参数二:队列的类型(串行或者并行)
dispatch_queue_t queue = dispatch_queue_create("com.alibaba.queue1", DISPATCH_QUEUE_SERIAL);

dispatch_async(queue, ^{
    NSLog(@"我是第一个任务,是否是主线程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第二个任务,是否是主线程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第三个任务,是否是主线程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第四个任务,是否是主线程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第五个任务,是否是主线程:%d",[NSThread isMainThread]);
});

}

点击按钮 打印出:

44675DD5-C101-4FDA-90D3-B3DE86DB17DE.png

8.延时执行

- (void)didClickedButton9:(UIButton *)button9
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          self.view.backgroundColor = [UIColor redColor];
});
}

点击按钮

27B7E06B-600C-4471-8916-1E231C34F096.png

9.只执行一次

- (void)didClickedButton10:(UIButton *)button10
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    NSLog(@"我只走一次");
});

}

点击按钮 打印出:

5871839E-24EC-4BC0-A4A7-749DCDDB0A2D.png

10.多次执行

    - (void)didClickedButton11:(UIButton *)button11
{
dispatch_queue_t queue = dispatch_queue_create("com.lanou3g.test", DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(3, queue, ^(size_t index) {
    NSLog(@"我走了 %ld 累死了都 ", index);
});

}

点击按钮 打印出:


8175C454-8884-4DC0-ABE5-22D0D222FBB7.png

11.线程互斥

这里举车站买票例子
- (void)didClickedButton12:(UIButton *)button12
{
self.count = 100; //票的总数
dispatch_queue_t queue = dispatch_queue_create("com.123.6.sellTicket", DISPATCH_QUEUE_CONCURRENT);
//创建线程锁对象
NSLock *lock = [NSLock new];
//开辟10个买票窗口
for (NSInteger i = 0; i < 10; i++) {
dispatch_async(queue, ^{
[lock lock]; //加锁

        //每个窗口可以卖10张票
        for (NSInteger j = 0; j < 10; j++) {
            NSLog(@"我买到了第 %ld 张票", self.count);
            self.count--;
            
        }
        [lock unlock]; //解锁

    });
    
}
}

点击按钮 打印出:


23C0C23A-E929-4470-A302-10C3FF2DA01F.png

每个不同按钮都有各自的方法,感兴趣的小伙伴可以试试哦


868D40F4-1BFA-461C-A61B-1253D6CA40A1.png

使用多线程的好处:

可以使CPU多个核同时使用,令计算机效率更高效化,以前单核的机器,同时有两个线程在运行时,是先把其中某线程先执行的形式,这样无疑延长了计算所有的时间,多核的情况下,一线程可以交给一个核去处理,另一个线程可以交给另一个核去处理,这个,计算机的资源利用就大大升高.减少用户等待时间。

什么时候使用多线程:

按生活原理.当你在吃饭的时候看电视,是不是大脑在同时控制你进行着两种工作?同理,计算机也一样,比如,软件在后台处理文件的时候,同时又显示给用户看与后台处理无关的内容,这时候,我们总不能等后台处理完了,执行显示.这时候多线程的优势就很明显了.

多线程主要用于计算机同时执行多个任务,而多个任务之间的执行是不互相影响的

希望大家在实际开发中熟练使用多线程,大家一同学习!!!

相关文章

网友评论

    本文标题:iOS开发-------多线程的基础使用方法

    本文链接:https://www.haomeiwen.com/subject/dbejpttx.html