//开辟主线程
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
];
}); //同步提交任务函数
<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"
);
});
//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
];
});
<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
(
@"
延时三秒后执行的任务
"
);
});
//
创建一个任务组
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
(
@"
任务三
"
);
});
//
为了保证数据访问时的安全性
,
可以使用
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
(
@"
任务被执行一次
"
);
});
}
//二.
创建
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];
//三.
应用程序进程会默认开辟一个线程
--
主线程
.
主线程的作用是更新
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
];
[
self
.
activityIndicator
startAnimating];