//开辟主线程
1.GCD方法,通过向主线程队列发送一个block块,使block里的方法可以在主线程中执行
dispatch_async(dispatch_get_main_queue( ),^{
//需要执行的方法
});
2.NSOperation方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; //主队列
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
//需要执行的方法
}];
[mainQueue addOperation:operation];
3.NSThread方法
[self performSelector:@selector(method) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES modes:nil];
[self performSelectorOnMainThread:@selector(method) withObject:nil waitUntilDone:YES];
[[NSThread mainThread] performSelector:@selector(method) withObject:nil];
4.RunLoop方法
[[NSRunLoop mainRunLoop] performSelector:@selector(method) withObject:nil];
子线程
//
应用程序进程会默认开辟一个线程
--
主线程
.
主线程的作用是更新
ui
界面
.
如果应用程序在运行过程中并不开辟其它线程
,
只有主线程可以完成任务操作
,
这种情形被称作单线程应用
.
单线程应用会出现一定程度的代码堵塞
,
导致用户界面假死
一,
GCD
的核心就是使用分发队列来管理任务的执行
,
分发队列分为两种
:
一种
serial(
串行
),
一种
concurrent(
并发
),
无论哪种队列都严格遵守
FIFO
//1.<1>
获取
serial queue
的两种方式
//
获取主线程队列
,mainQueue
会在主线程中执行
.
即
:
主线程会执行
mainQueue
中的各个任务
dispatch_queue_t
mainQueue =
dispatch_get_main_queue
();
// 为主线程队列提交任务 , 任务以 block 形式提交
dispatch_async (mainQueue, ^{
NSLog ( @" 第一个任务 " );
});
dispatch_async (mainQueue, ^{
NSLog ( @" 第二个任务 " );
[ self calculate ];
}); // 在 block 中写要被执行的代码片段 , 也可以是方法的调用
dispatch_sync (mainQueue, ^{
NSLog ( @" 第三个任务 " );
[ self downloadImage ];
// 为主线程队列提交任务 , 任务以 block 形式提交
dispatch_async (mainQueue, ^{
NSLog ( @" 第一个任务 " );
});
dispatch_async (mainQueue, ^{
NSLog ( @" 第二个任务 " );
[ self calculate ];
}); // 在 block 中写要被执行的代码片段 , 也可以是方法的调用
dispatch_sync (mainQueue, ^{
NSLog ( @" 第三个任务 " );
[ self downloadImage ];
}); //同步提交任务函数
<2>
除了可以获取主队列这种串行队列
,
还可以根据需求自己创建串行队列
dispatch_queue_t
mySerialQueue =
dispatch_queue_create
(
"com.lanou3g.GCD.mySerialQueue"
,
DISPATCH_QUEUE_SERIAL
);
//
第一个参数是给当前创建的队列起名
,
苹果官方推荐使用反向域名命名
,
第二个参数是指定当前创建的队列的类型
,
分为
Serial
和
Concurrent
两种
// 自定义的串行队列在分发执行任务时开辟子线程来执行
dispatch_async (mySerialQueue, ^{
NSLog ( @"first mission:%@" ,[ NSThread isMainThread ] ? @" is main thread" : @"isn't main thread" );
});
dispatch_async (mySerialQueue, ^{
NSLog ( @"second mission:%@" ,[ NSThread isMainThread ] ? @" is main thread" : @"isn't main thread" );
});
dispatch_async (mySerialQueue, ^{
NSLog ( @"third mission:%@" ,[ NSThread isMainThread ] ? @" is main thread" : @"isn't main thread" );
// 自定义的串行队列在分发执行任务时开辟子线程来执行
dispatch_async (mySerialQueue, ^{
NSLog ( @"first mission:%@" ,[ NSThread isMainThread ] ? @" is main thread" : @"isn't main thread" );
});
dispatch_async (mySerialQueue, ^{
NSLog ( @"second mission:%@" ,[ NSThread isMainThread ] ? @" is main thread" : @"isn't main thread" );
});
dispatch_async (mySerialQueue, ^{
NSLog ( @"third mission:%@" ,[ NSThread isMainThread ] ? @" is main thread" : @"isn't main thread" );
});
//2.
获取并发队列也有两种方法
<1>
dispatch_queue_t
globalQueue =
dispatch_get_global_queue
(
DISPATCH_QUEUE_PRIORITY_HIGH
,
0
);
//
第一参数是用来控制队列的优先级的
,
第二个参数是苹果预留的参数
,
未来才会使用
,
目前设置为
0
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (- 2 )
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
//globalQueue 作为并发队列 , 会开辟若干个子线程来并发执行多个提交的任务 ( 开始较晚的任务不一定最后结束 , 开始较早的任务也不一定最先完成 )
dispatch_async (globalQueue, ^{
NSLog ( @"fisrt mission:%@" ,[ NSThread isMainThread ] ? @"is main thread" : @"isn't main thread" );
[ self calculate ];
});
dispatch_async (globalQueue, ^{
NSLog ( @"second mission:%@" ,[ NSThread isMainThread ] ? @"is main thread" : @"isn't main thread" );
[ self downloadImage ];
});
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (- 2 )
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
//globalQueue 作为并发队列 , 会开辟若干个子线程来并发执行多个提交的任务 ( 开始较晚的任务不一定最后结束 , 开始较早的任务也不一定最先完成 )
dispatch_async (globalQueue, ^{
NSLog ( @"fisrt mission:%@" ,[ NSThread isMainThread ] ? @"is main thread" : @"isn't main thread" );
[ self calculate ];
});
dispatch_async (globalQueue, ^{
NSLog ( @"second mission:%@" ,[ NSThread isMainThread ] ? @"is main thread" : @"isn't main thread" );
[ self downloadImage ];
});
<2>自己创建并发队列
dispatch_queue_t myConcurrentQueue = dispatch_queue_create ( "com.lanou3g.GCD.myConcurrentQueue" , DISPATCH_QUEUE_CONCURRENT );
dispatch_async
(myConcurrentQueue, ^{
NSLog ( @"fisrt mission:%@" ,[ NSThread isMainThread ] ? @"is main thread" : @"isn't main thread" );
[ self calculate ];
});
dispatch_async (myConcurrentQueue, ^{
NSLog ( @"second mission:%@" ,[ NSThread isMainThread ] ? @"is main thread" : @"isn't main thread" );
[ self downloadImage ];
});
// 延时提交某个任务到分发队列中
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 3 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
NSLog ( @" 延时三秒后执行的任务 " );
});
// 延时执行任务可以在 mainQueue 中正常执行 , 在自定义的队列中执行就会出现问题
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 3 * NSEC_PER_SEC )), myConcurrentQueue, ^{
NSLog ( @" 延时三秒后执行的任务 " );
NSLog ( @"fisrt mission:%@" ,[ NSThread isMainThread ] ? @"is main thread" : @"isn't main thread" );
[ self calculate ];
});
dispatch_async (myConcurrentQueue, ^{
NSLog ( @"second mission:%@" ,[ NSThread isMainThread ] ? @"is main thread" : @"isn't main thread" );
[ self downloadImage ];
});
// 延时提交某个任务到分发队列中
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 3 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
NSLog ( @" 延时三秒后执行的任务 " );
});
// 延时执行任务可以在 mainQueue 中正常执行 , 在自定义的队列中执行就会出现问题
dispatch_after ( dispatch_time ( DISPATCH_TIME_NOW , ( int64_t )( 3 * NSEC_PER_SEC )), myConcurrentQueue, ^{
NSLog ( @" 延时三秒后执行的任务 " );
});
//
创建一个任务组
dispatch_group_t
group =
dispatch_group_create
();
dispatch_group_async (group, myConcurrentQueue, ^{
NSLog ( @" 任务一 " );
});
dispatch_group_async (group, myConcurrentQueue, ^{
NSLog ( @" 任务二 " );
[ self calculate ];
});
dispatch_group_notify (group, myConcurrentQueue, ^{
NSLog ( @" 任务三 " );
dispatch_group_async (group, myConcurrentQueue, ^{
NSLog ( @" 任务一 " );
});
dispatch_group_async (group, myConcurrentQueue, ^{
NSLog ( @" 任务二 " );
[ self calculate ];
});
dispatch_group_notify (group, myConcurrentQueue, ^{
NSLog ( @" 任务三 " );
});
//
为了保证数据访问时的安全性
,
可以使用
serial queue
来解决访问的安全性问题
//serial queue 缺陷 : 后面的任务必须等待前面的任务执行结束后再执行 , 降低数据读取的效率
// 如果只是读取数据 , 适合使用 concurret queue
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务一 " );
});
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务二 " );
});
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务三 " );
});
dispatch_barrier_async (myConcurrentQueue, ^{
NSLog ( @" 写入数据任务 " );
[ self calculate ];
}); //barrier_async 会等待它之前被提交的任务并发执行完后 , 才开始执行 , 并且执行完成后才开始执行后来被提交的任务 , 像一道墙 , 隔开了之前和之后提交的任务 . 这样的操作可以既保证读写的安全性 , 也可以提高读写的效率
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务四 " );
});
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务五 " );
});
for ( int i = 0 ; i < 10 ; i++) {
static dispatch_once_t onceToken;
dispatch_once (&onceToken, ^{
NSLog ( @" 任务被执行一次 " );
});
//serial queue 缺陷 : 后面的任务必须等待前面的任务执行结束后再执行 , 降低数据读取的效率
// 如果只是读取数据 , 适合使用 concurret queue
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务一 " );
});
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务二 " );
});
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务三 " );
});
dispatch_barrier_async (myConcurrentQueue, ^{
NSLog ( @" 写入数据任务 " );
[ self calculate ];
}); //barrier_async 会等待它之前被提交的任务并发执行完后 , 才开始执行 , 并且执行完成后才开始执行后来被提交的任务 , 像一道墙 , 隔开了之前和之后提交的任务 . 这样的操作可以既保证读写的安全性 , 也可以提高读写的效率
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务四 " );
});
dispatch_async (myConcurrentQueue, ^{
NSLog ( @" 读取数据任务五 " );
});
for ( int i = 0 ; i < 10 ; i++) {
static dispatch_once_t onceToken;
dispatch_once (&onceToken, ^{
NSLog ( @" 任务被执行一次 " );
});
}
//二.
创建
NSInvocationOperation
对象
NSInvocationOperation
*invoOperation = [[[
NSInvocationOperation
alloc
]
initWithTarget
:
self
selector
:
@selector
(calculate)
object
:
nil
]
autorelease
];
// [invoOperation start];
// 创建 NSBlockOperation 对象
NSBlockOperation *blockOperation = [ NSBlockOperation blockOperationWithBlock :^{
[ self downloadImage ];
}];
// [blockOperation start];
// 创建操作队列 , 通过操作队列完成操作对象的执行
// NSOperationQueue *queue = [NSOperationQueue mainQueue]; // 创建主线程队列
NSOperationQueue *queue = [[[ NSOperationQueue alloc ] init ] autorelease ]; // 自己创建的操作队列在执行相关操作对象时 , 会根据需求开辟子线程取执行
[queue setMaxConcurrentOperationCount : 2 ]; // 设置最大并发数 , 最大并发数如果是 1, 则表示队列中的操作被顺序执行 , 只有某个操作完成后才继续执行下一个操作
[blockOperation setQueuePriority : NSOperationQueuePriorityVeryHigh ];
[invoOperation setQueuePriority : NSOperationQueuePriorityVeryLow ];
[queue addOperation :invoOperation];
[queue addOperation :blockOperation];
// [invoOperation start];
// 创建 NSBlockOperation 对象
NSBlockOperation *blockOperation = [ NSBlockOperation blockOperationWithBlock :^{
[ self downloadImage ];
}];
// [blockOperation start];
// 创建操作队列 , 通过操作队列完成操作对象的执行
// NSOperationQueue *queue = [NSOperationQueue mainQueue]; // 创建主线程队列
NSOperationQueue *queue = [[[ NSOperationQueue alloc ] init ] autorelease ]; // 自己创建的操作队列在执行相关操作对象时 , 会根据需求开辟子线程取执行
[queue setMaxConcurrentOperationCount : 2 ]; // 设置最大并发数 , 最大并发数如果是 1, 则表示队列中的操作被顺序执行 , 只有某个操作完成后才继续执行下一个操作
[blockOperation setQueuePriority : NSOperationQueuePriorityVeryHigh ];
[invoOperation setQueuePriority : NSOperationQueuePriorityVeryLow ];
[queue addOperation :invoOperation];
[queue addOperation :blockOperation];
//三.
应用程序进程会默认开辟一个线程
--
主线程
.
主线程的作用是更新
ui
界面
.
如果应用程序在运行过程中并不开辟其它线程
,
只有主线程可以完成任务操作
,
这种情形被称作单线程应用
.
单线程应用会出现一定程度的代码堵塞
,
导致用户界面假死
// 开辟子线程方法一 :
NSThread *aThread = [[[ NSThread alloc ] initWithTarget : self selector : @selector (calculate) object : nil ] autorelease ]; // 开辟新的子线程并附加对应的方法 , 等待被执行
aThread. name = @" 子线程一 " ;
// 为子线程对象发送 start 信息 , 开启线程 , 执行相关方法
[aThread start ];
// 开辟子线程方法二 :
[ NSThread detachNewThreadSelector : @selector (calculate) toTarget : self withObject : nil ];
[ NSThread detachNewThreadSelector : @selector (downloadImage) toTarget : self withObject : nil ];
// 开辟子线程方法一 :
NSThread *aThread = [[[ NSThread alloc ] initWithTarget : self selector : @selector (calculate) object : nil ] autorelease ]; // 开辟新的子线程并附加对应的方法 , 等待被执行
aThread. name = @" 子线程一 " ;
// 为子线程对象发送 start 信息 , 开启线程 , 执行相关方法
[aThread start ];
// 开辟子线程方法二 :
[ NSThread detachNewThreadSelector : @selector (calculate) toTarget : self withObject : nil ];
[ NSThread detachNewThreadSelector : @selector (downloadImage) toTarget : self withObject : nil ];
[
self
.
activityIndicator
startAnimating];