多线程的基本概念
每一个程序都有一个主线程,程序启动时创建(调用main来启动)
主线程的生命周期是和应用程序绑定的,程序退出(结束)时,主线程也就停止了
多线程技术表示,一个应用程序有多个线程,使用多线程能提供CPU的使用率,防止主线程堵塞
任何有可能堵塞主线程的任务不要在主线程执行(访问网络)
进程相当于容器 线程相当于路径
参看课件中的 main.jpg
线程的创建
线程的创建与启动
// 1. 第一种开启新的线程调用 mutableThread
NSThread *t = [[NSThread alloc] initWithTarget:self
selector:@selector(mutableThread)
object:nil];
[t start]; // 需要手动开启
// 2. 第二种开启新的线程调用 mutableThread
[NSThread detachNewThreadSelector:@selector(mutableThread)
toTarget:self withObject:nil];
// 3. 第三种开启新的线程调用 mutableThread
[self performSelectorInBackground:@selector(mutableThread)
withObject:nil];
// 4.block语法启动一个线程
NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
[threadQueue addOperationWithBlock:^(void) {
NSThread *t = [NSThread currentThread];
if (![t isMainThread]) {
NSLog(@"是多线程");
}
}];
// 5.NSOperation开启一个线程
NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
NSInvocationOperation *op = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(mutableThread)
object:nil];
[threadQueue addOperation:op];
// 在主线程上调用 reloadData 方法
[self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
project: ThreadDemo
打开 AppDelegate.m
在 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中的
[self.window makeKeyAndVisible]; 下面加入
//----------1.第一种方式:创建多线程对象
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mutableThread:) object:@"test"];
//开始运行多线程
[thread start];
for (int i=0; i<100; i++) {
NSLog(@"--主线程-%d",i);
}
在加入方法
- (void)mutableThread:(NSString *)t {
for (int i=0; i<100; i++) {
NSLog(@"--多线程1-%d",i);
}
}
运行 交替执行
mutableThread方法执行完线程 thread 就会销毁
将
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mutableThread:) object:@"test"];
//开始运行多线程
[thread start];
注释掉 在其下加入
//-----------2.第二种方式
[NSThread detachNewThreadSelector:@selector(mutableThread:) toTarget:self withObject:nil];
运行
将 [NSThread detachNewThreadSelector:@selector(mutableThread:) toTarget:self withObject:nil]; 注释掉 在其下加入
//-----------3.第三种方式
[self performSelectorInBackground:@selector(mutableThread:) withObject:nil];
运行
将 [self performSelectorInBackground:@selector(mutableThread:) withObject:nil]; 注释掉在其下加入
[self mutableThread:nil];
运行 非并发运行
将 [self mutableThread:nil]; 注释掉 在其下加入
//-----------4.第四种方式block语法启动一个线程 不用创建需要调用的方法
//NSOperationQueue相当于一个线程池
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperationWithBlock:^{
for (int i=0; i<100; i++) {
NSLog(@"--多线程-%d",i);
}
}];
运行
将
//NSOperationQueue相当于一个线程池
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperationWithBlock:^{
for (int i=0; i<100; i++) {
NSLog(@"--多线程-%d",i);
}
}];
注释掉 在其下加入
//-----------5.第五种方式
//创建一个线程队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
//创建一个线程操作对象
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(mutableThread:) object:nil];
//创建一个线程操作对象
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(mutableThread2:) object:nil];
//将线程添加到线程队列中 并发运行
[operationQueue addOperation:operation1];
[operationQueue addOperation:operation2];
在类中加入方法
- (void)mutableThread2:(NSString *)t {
for (int i=0; i<100; i++) {
NSLog(@"--多线程2-%d",i);
}
}
运行
在 NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 下面加入
//设置线程执行的并发数 表示只会执行一个线程
//第一个执行完后才会执行第二个线程
operationQueue.maxConcurrentOperationCount = 1;
运行
在
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(mutableThread2:) object:nil];
下面加入
//设置线程的优先级 共5个优先级
operation2.queuePriority = NSOperationQueuePriorityHigh;
运行
在 mutableThread 方法中的
for (int i=0; i<100; i++) {
NSLog(@"--多线程1-%d",i);
}
下面加入
//跳到主线程执行 参数yes表示等方法mainThread执行完在向下继续执行 如果为NO不需要等待线程方法调用完就会继续向下执行
[self performSelectorOnMainThread:@selector(mainThread) withObject:nil waitUntilDone:YES];
//...
在类中加入
- (void)mainThread {
//判断当前线程是否为主线程
BOOL isMain = [NSThread isMainThread];
if (isMain) {
NSLog(@"mainThread");
}
}
运行
多线程的常用方法
NSThread的常用方法
// 判断当前线程是否是多线程
+ (BOOL)isMultiThreaded;
// 获取当前线程对象
+ (NSThread *)currentThread;
// 使当前线程睡眠指定的时间,单位为秒
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 退出当前线程
+ (void)exit;
// 判断当前线程是否为主线程
+ (BOOL)isMainThread
// 启动该线程
- (void)start
GCD
GCD(Grand Central Dispatch)是一个大的主题。它可以提高代码的执行效率与多核的利用率。
//创建一个队列
dispatch_queue_t queue = dispatch_queue_create("test", NULL);
//创建异步线程
dispatch_async(queue, ^{
//多线程
//回到主线程执行
dispatch_sync(dispatch_get_main_queue(), ^{
//主线程
});
});
将 第五种方式 注释掉 在其下加入
//-----------------6.第六种方式:GCD 开源项目
//创建一个队列
dispatch_queue_t queue = dispatch_queue_create("test", NULL);
dispatch_async(queue, ^{
for (int i=0; i<100; i++) {
NSLog(@"--多线程1-%d",i);
}
});
运行
在
for (int i=0; i<100; i++) {
NSLog(@"--多线程1-%d",i);
}
下面加入
BOOL isMuliti = [NSThread isMultiThreaded];
if (isMuliti) {
NSLog(@"多线程");
}
//回到主线程
dispatch_sync(dispatch_get_main_queue(), ^{
BOOL isMain = [NSThread isMainThread];
if (isMain) {
NSLog(@"主线程");
}
});
运行
在
for (int i=0; i<100; i++) {
NSLog(@"--主线程-%d",i);
}
return YES;
顶上加入
//通过此种方式,还是同步运行在当前线程上
dispatch_sync(queue, ^{
//当前线程
});
注意 dispatch_sync同步 与 dispatch_async异步 区别
dispatch_queue_create() 的第二个参数可以选 DISPATCH_QUEUE_CONCURRENT,这样创建出来的queue就是并发的了。
dispatch_async() 调用以后立即返回,dispatch_sync() 调用以后等到block执行完以后才返回,dispatch_sync()会阻塞当前线程。
dispatch_async与dispatch_sync的不同,一个是把工作交给queue就不管了,一个是交出工作后等queue执行完当前代码才走下一步。对于serial queue(dispatch_queue_create创建的)来说,它里面的block们都是串行FIFO的,不可能并行。
我们可以将许多 blocks 用 dispatch_async 函数提交到到 dispatch_queue 串行运行。这些 blocks 是按照 FIFO(先入先出)规则调度的,也就是说,先加入的先执行,后加入的一定后执行,但在某一个时刻,可能有多个 block 同时在执行。
根据所学多线程知识实现5个售票窗口同时发售火车票功能
//创建一个队列
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[self mainThread];
});
dispatch_async(queue, ^{
[self mainThread];
});
dispatch_async(queue, ^{
[self mainThread];
});
dispatch_async(queue, ^{
[self mainThread];
});
dispatch_async(queue, ^{
[self mainThread];
});
调用方法
- (void)mainThread {
while (thicket>0) {
NSLog(@"已售出第%i",thicket);
--thicket;
}
}
自动释放池
子线程的内存管理
新创建的子线程需要添加自动释放池管理内存
// 创建子线程
[self performSelectorInBackground:@selector(mutableThread)
withObject:nil];
- (void)mutableThread {
// 创建自动释放池
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (int i=0; i<10; i++) {
NSLog(@"%d",i);
[NSThread sleepForTimeInterval:1];
}
[self performSelectorOnMainThread:@selector(reloadData)
withObject:nil waitUntilDone:NO];
[pool release];
}
每一个程序都有一个主线程,程序启动时创建(调用main来启动)
主线程的生命周期是和应用程序绑定的,程序退出(结束)时,主线程也就停止了
多线程技术表示,一个应用程序有多个线程,使用多线程能提供CPU的使用率,防止主线程堵塞
任何有可能堵塞主线程的任务不要在主线程执行(访问网络)
进程相当于容器 线程相当于路径
参看课件中的 main.jpg
线程的创建
线程的创建与启动
// 1. 第一种开启新的线程调用 mutableThread
NSThread *t = [[NSThread alloc] initWithTarget:self
selector:@selector(mutableThread)
object:nil];
[t start]; // 需要手动开启
// 2. 第二种开启新的线程调用 mutableThread
[NSThread detachNewThreadSelector:@selector(mutableThread)
toTarget:self withObject:nil];
// 3. 第三种开启新的线程调用 mutableThread
[self performSelectorInBackground:@selector(mutableThread)
withObject:nil];
// 4.block语法启动一个线程
NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
[threadQueue addOperationWithBlock:^(void) {
NSThread *t = [NSThread currentThread];
if (![t isMainThread]) {
NSLog(@"是多线程");
}
}];
// 5.NSOperation开启一个线程
NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
NSInvocationOperation *op = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(mutableThread)
object:nil];
[threadQueue addOperation:op];
// 在主线程上调用 reloadData 方法
[self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
project: ThreadDemo
打开 AppDelegate.m
在 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中的
[self.window makeKeyAndVisible]; 下面加入
//----------1.第一种方式:创建多线程对象
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mutableThread:) object:@"test"];
//开始运行多线程
[thread start];
for (int i=0; i<100; i++) {
NSLog(@"--主线程-%d",i);
}
在加入方法
- (void)mutableThread:(NSString *)t {
for (int i=0; i<100; i++) {
NSLog(@"--多线程1-%d",i);
}
}
运行 交替执行
mutableThread方法执行完线程 thread 就会销毁
将
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mutableThread:) object:@"test"];
//开始运行多线程
[thread start];
注释掉 在其下加入
//-----------2.第二种方式
[NSThread detachNewThreadSelector:@selector(mutableThread:) toTarget:self withObject:nil];
运行
将 [NSThread detachNewThreadSelector:@selector(mutableThread:) toTarget:self withObject:nil]; 注释掉 在其下加入
//-----------3.第三种方式
[self performSelectorInBackground:@selector(mutableThread:) withObject:nil];
运行
将 [self performSelectorInBackground:@selector(mutableThread:) withObject:nil]; 注释掉在其下加入
[self mutableThread:nil];
运行 非并发运行
将 [self mutableThread:nil]; 注释掉 在其下加入
//-----------4.第四种方式block语法启动一个线程 不用创建需要调用的方法
//NSOperationQueue相当于一个线程池
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperationWithBlock:^{
for (int i=0; i<100; i++) {
NSLog(@"--多线程-%d",i);
}
}];
运行
将
//NSOperationQueue相当于一个线程池
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperationWithBlock:^{
for (int i=0; i<100; i++) {
NSLog(@"--多线程-%d",i);
}
}];
注释掉 在其下加入
//-----------5.第五种方式
//创建一个线程队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
//创建一个线程操作对象
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(mutableThread:) object:nil];
//创建一个线程操作对象
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(mutableThread2:) object:nil];
//将线程添加到线程队列中 并发运行
[operationQueue addOperation:operation1];
[operationQueue addOperation:operation2];
在类中加入方法
- (void)mutableThread2:(NSString *)t {
for (int i=0; i<100; i++) {
NSLog(@"--多线程2-%d",i);
}
}
运行
在 NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; 下面加入
//设置线程执行的并发数 表示只会执行一个线程
//第一个执行完后才会执行第二个线程
operationQueue.maxConcurrentOperationCount = 1;
运行
在
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(mutableThread2:) object:nil];
下面加入
//设置线程的优先级 共5个优先级
operation2.queuePriority = NSOperationQueuePriorityHigh;
运行
在 mutableThread 方法中的
for (int i=0; i<100; i++) {
NSLog(@"--多线程1-%d",i);
}
下面加入
//跳到主线程执行 参数yes表示等方法mainThread执行完在向下继续执行 如果为NO不需要等待线程方法调用完就会继续向下执行
[self performSelectorOnMainThread:@selector(mainThread) withObject:nil waitUntilDone:YES];
//...
在类中加入
- (void)mainThread {
//判断当前线程是否为主线程
BOOL isMain = [NSThread isMainThread];
if (isMain) {
NSLog(@"mainThread");
}
}
运行
多线程的常用方法
NSThread的常用方法
// 判断当前线程是否是多线程
+ (BOOL)isMultiThreaded;
// 获取当前线程对象
+ (NSThread *)currentThread;
// 使当前线程睡眠指定的时间,单位为秒
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 退出当前线程
+ (void)exit;
// 判断当前线程是否为主线程
+ (BOOL)isMainThread
// 启动该线程
- (void)start
GCD
GCD(Grand Central Dispatch)是一个大的主题。它可以提高代码的执行效率与多核的利用率。
//创建一个队列
dispatch_queue_t queue = dispatch_queue_create("test", NULL);
//创建异步线程
dispatch_async(queue, ^{
//多线程
//回到主线程执行
dispatch_sync(dispatch_get_main_queue(), ^{
//主线程
});
});
将 第五种方式 注释掉 在其下加入
//-----------------6.第六种方式:GCD 开源项目
//创建一个队列
dispatch_queue_t queue = dispatch_queue_create("test", NULL);
dispatch_async(queue, ^{
for (int i=0; i<100; i++) {
NSLog(@"--多线程1-%d",i);
}
});
运行
在
for (int i=0; i<100; i++) {
NSLog(@"--多线程1-%d",i);
}
下面加入
BOOL isMuliti = [NSThread isMultiThreaded];
if (isMuliti) {
NSLog(@"多线程");
}
//回到主线程
dispatch_sync(dispatch_get_main_queue(), ^{
BOOL isMain = [NSThread isMainThread];
if (isMain) {
NSLog(@"主线程");
}
});
运行
在
for (int i=0; i<100; i++) {
NSLog(@"--主线程-%d",i);
}
return YES;
顶上加入
//通过此种方式,还是同步运行在当前线程上
dispatch_sync(queue, ^{
//当前线程
});
注意 dispatch_sync同步 与 dispatch_async异步 区别
dispatch_queue_create() 的第二个参数可以选 DISPATCH_QUEUE_CONCURRENT,这样创建出来的queue就是并发的了。
dispatch_async() 调用以后立即返回,dispatch_sync() 调用以后等到block执行完以后才返回,dispatch_sync()会阻塞当前线程。
dispatch_async与dispatch_sync的不同,一个是把工作交给queue就不管了,一个是交出工作后等queue执行完当前代码才走下一步。对于serial queue(dispatch_queue_create创建的)来说,它里面的block们都是串行FIFO的,不可能并行。
我们可以将许多 blocks 用 dispatch_async 函数提交到到 dispatch_queue 串行运行。这些 blocks 是按照 FIFO(先入先出)规则调度的,也就是说,先加入的先执行,后加入的一定后执行,但在某一个时刻,可能有多个 block 同时在执行。
根据所学多线程知识实现5个售票窗口同时发售火车票功能
//创建一个队列
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[self mainThread];
});
dispatch_async(queue, ^{
[self mainThread];
});
dispatch_async(queue, ^{
[self mainThread];
});
dispatch_async(queue, ^{
[self mainThread];
});
dispatch_async(queue, ^{
[self mainThread];
});
调用方法
- (void)mainThread {
while (thicket>0) {
NSLog(@"已售出第%i",thicket);
--thicket;
}
}
自动释放池
子线程的内存管理
新创建的子线程需要添加自动释放池管理内存
// 创建子线程
[self performSelectorInBackground:@selector(mutableThread)
withObject:nil];
- (void)mutableThread {
// 创建自动释放池
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (int i=0; i<10; i++) {
NSLog(@"%d",i);
[NSThread sleepForTimeInterval:1];
}
[self performSelectorOnMainThread:@selector(reloadData)
withObject:nil waitUntilDone:NO];
[pool release];
}