实际开发中多线程的使用时非常常见的,多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。可以提高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];
}

点击按钮

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];
}
点击按钮


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];
}

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

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

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];
}
点击按钮

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];
}
}
点击按钮 打印出:

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]);
});
}
点击按钮 打印出:

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];
});
}
点击按钮

9.只执行一次
- (void)didClickedButton10:(UIButton *)button10
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"我只走一次");
});
}
点击按钮 打印出:

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);
});
}
点击按钮 打印出:

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]; //解锁
});
}
}
点击按钮 打印出:

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

使用多线程的好处:
可以使CPU多个核同时使用,令计算机效率更高效化,以前单核的机器,同时有两个线程在运行时,是先把其中某线程先执行的形式,这样无疑延长了计算所有的时间,多核的情况下,一线程可以交给一个核去处理,另一个线程可以交给另一个核去处理,这个,计算机的资源利用就大大升高.减少用户等待时间。
什么时候使用多线程:
按生活原理.当你在吃饭的时候看电视,是不是大脑在同时控制你进行着两种工作?同理,计算机也一样,比如,软件在后台处理文件的时候,同时又显示给用户看与后台处理无关的内容,这时候,我们总不能等后台处理完了,执行显示.这时候多线程的优势就很明显了.
多线程主要用于计算机同时执行多个任务,而多个任务之间的执行是不互相影响的
希望大家在实际开发中熟练使用多线程,大家一同学习!!!
网友评论