#import "ViewController.h"
#import "MyNSOperation.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
/*
程序:由源代码生成的可执行应用.(例如:QQ.app)
进程:一个正在运行的程序可以看做一个进程.(例如正在运行的qq就是一个进程),进程拥有独立运行所需的全部资源.
线程:程序中独立运行的代码段.(例如:接收QQ消息的代码)
一个进程是由一个或者多个线程组成.进程只负责资源的调度和分配,线程才是真正的执行单元,负责代码的执行
*/
/*
单线程
每个正在运行的程序(即进程),至少包含一个线程,这个线程叫主线程.
主线程:主线程在程序启东时被创建,用于执行main函数.
只有一个主线程的程序,称作单线程程序
在单线程程序中,主线程负责执行程序的所有代码(UI展现以及刷新,网络请求 ,本地存储等等).这些代码只能顺序执行,无法并发执行.
*/
/*
拥有多个线程的程序,称作多线程程序
iOS允许用户开辟新的线程,相对于主线程来讲,这些线程,称作子线程.
可以根据需要开辟若干个子线程.
子线程和主线程都是独立的运行单元,各自的执行互不影响,因此能够并发执行.
*/
/*
单线程,多线程的区别
单线程程序:只有一个线程,即主线程,代码顺序执行,容易出现代码阻塞(页面假死).
多线程程序:有多个线程,线程间独立运行,能有效的避免代码阻塞,并且提高程序的运行性能.
注意:iOS中关于UI的添加和刷新必须在主线程中操作
*/
/*
iOS多线程实现种类:
1.NSThread;(轻量级的多线程)
2.NSOperationQueue
3.NSObject
4.GCD
*/
//NSThread有两种多线程的写法,一种手动取开辟,一种自动去开辟
//自动开辟子线程
// [NSThread detachNewThreadSelector:@selector(downloadmp3) toTarget:self withObject:nil];
//本方法实现是手动的
// NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadmp3) object:nil];
//手动取执行线程
// [thread start];
//结束线程有两种方式
//第一种:给线程发送结束消息
// [thread cancel];
// //第二种:立即结束进程
// [NSThread exit];
//判断一个线程是否正在执行
// BOOL bb = [thread isExecuting];
// if (bb) {
// NSLog(@"线程有执行");
// }
// //判断一个线程是否完成了任务(是否执行完毕)
// BOOL aa = [thread isFinished];
// if (aa) {
// NSLog(@"任务完成");
// }
//NSObject实现异步后台执行
//NSObject存在一个最简单的后台执行的方法(后台执行某个方法)
//[thread performSelectorInBackground:@selector(<#selector#>) withObject:<#(nullable id)#>]
}
- (IBAction)StopMainThread:(id)sender {
//怎么阻塞主线程,主线程中做耗时操作
NSLog(@"%@--->",[NSThread currentThread]);
long number = 0;
for (long i = 0; i<=1000000000; i++) {
number = number+i;
}
NSLog(@"%ld",number);
}
//用NSThread实现 用NSData下载一首MP3不允许卡住屏幕
- (IBAction)downLoadMP3:(id)sender {
//点击button的时候开辟子线程
//需要联网
[NSThread detachNewThreadSelector:@selector(downloadMp3) toTarget:self withObject:nil];
}
-(void)downloadMp3
{
NSString *str = @"http://60.190.216.110:8880/accompany_onlinePlay_130115exut/memberaccompany/songfolder/2009/11/13/608c3024c9f941ce8bf64f6ed4051c34.mp3";
NSURL *url = [NSURL URLWithString:str];
NSData *data = [NSData dataWithContentsOfURL:url];
NSString *docpath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *mp3path = [docpath stringByAppendingPathComponent:@"说谎.MP3"];
NSLog(@"%@",mp3path);
NSFileManager *manager = [NSFileManager defaultManager];
[manager createFileAtPath:mp3path contents:data attributes:nil];
}
//锁(线程不重复访问)
- (IBAction)Touchlock:(id)sender {
//开3个线程
NSLock *lock = [[NSLock alloc] init];
NSThread *t1 = [[NSThread alloc] initWithTarget:self selector:@selector(buyticket:) object:lock];
NSThread *t2 = [[NSThread alloc] initWithTarget:self selector:@selector(buyticket:) object:lock];
NSThread *t3 = [[NSThread alloc] initWithTarget:self selector:@selector(buyticket:) object:lock];
[t1 start];
[t2 start];
[t3 start];
}
-(void)buyticket:(id)object
{
NSLock *lock = (NSLock *)object;
static NSInteger ticket= 10;
while (YES) {
[lock lock];
sleep(1);
ticket--;
NSLog(@"%ld",ticket);
if (ticket == 0) {
break;
}
[lock unlock];
}
}
//NSOperation(有两种开辟子线程的方式)
- (IBAction)NSOperation:(id)sender {
/* //1.用子类创建
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(StopMainThread2) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(StopMainThread2) object:nil];
NSInvocationOperation *op3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(StopMainThread2) object:nil];
//创建线程池
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//设置最大并行个数
//一个个执行
[queue setMaxConcurrentOperationCount:1];
//将三个线程放入池中
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];*/
//第二种方式 需要自己创建一个类 继承自NSOperation
//然后将耗时操作写到main函数
MyNSOperation *myop1 = [[MyNSOperation alloc] init];
MyNSOperation *myop2 = [[MyNSOperation alloc] init];
MyNSOperation *myop3 = [[MyNSOperation alloc] init];
//创建池
NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
[queue1 addOperation:myop1];
[queue1 addOperation:myop2];
[queue1 addOperation:myop3];
}
-(void)StopMainThread2
{
//1+2+3+....+1000000000
long number = 0 ;
for (long i = 0 ; i<= 1000000000; i++) {
number = number +i;
}
NSLog(@"%ld",number);
}
#pragma mark 主要开辟子线程的方式:GCD
- (IBAction)TouchGCD:(id)sender {
//主要的(需要记住的)保留了一些c的东西
//最常用的一种 一个子线程然后回到主线程
//开子线程 子线程里可以直接回到主线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
long number = 0 ;
for (long i = 0 ; i<= 100000000; i++) {
number = number +i;
}
NSLog(@"%ld",number);
//可以直接回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"计算结束了,回到主线程");
});
});
//分组管理 所有线程执行结束汇总
//创建queue
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//创建分组
dispatch_group_t group = dispatch_group_create();
//子线程1
dispatch_group_async(group, queue, ^{
sleep(1);
NSLog(@"111");
});
//子线程2
dispatch_group_async(group, queue, ^{
sleep(2);
NSLog(@"222");
});
//子线程3
dispatch_group_async(group, queue, ^{
sleep(3);
NSLog(@"333");
});
//1,2,3走完了才能走的
dispatch_group_notify(group, queue, ^{
NSLog(@"1,2,3已经结束");
});
//"路障"(障碍)roadblock
dispatch_queue_t queue1 = dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT);
//线程1
dispatch_async(queue1, ^{
NSLog(@"1");
});
//线程2
dispatch_async(queue1, ^{
NSLog(@"2");
});
//"路障"(障碍物)
dispatch_barrier_async(queue1, ^{
NSLog(@"3障碍物走");
});
//线程3
dispatch_async(queue1, ^{
NSLog(@"4最后走");
});
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
//自己写了一个继承自NSOperation的类
//.h没有东西
#import "MyNSOperation.h"
@implementation MyNSOperation
-(void)main
{
long number = 0 ;
for (long i = 0 ; i<= 1000000000; i++) {
number = number +i;
}
NSLog(@"%ld",number);
}
@end
多线程
最新推荐文章于 2024-12-01 23:53:39 发布