原文:http://blog.sina.com.cn/s/blog_7b9d64af0101cajz.html
任何一个 iOS 应用程序都是由一个或者多个线程构成的。无论你是否显示的使用了多线程编程技术,至少有 1 个 线程被创建。该线程叫做”main UI 线程”,被附加到主事件处理循环中(main run loop)。
多线程就是为了提高引用程序的工作效率!避免阻塞主线程!
当我们没有用任何多线程技术的话,默认情况下,是在程序的主线程中执行相关操作!
主线程执行任务
贴个单线程(主线程)执行任务的例子:
// 任务1
- (void) firstCounter{
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"First Counter = %lu", (unsigned long)counter); }
}
// 任务2
- (void) secondCounter{
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"Second Counter = %lu", (unsigned long)counter); }
}
// 任务3
- (void) thirdCounter{
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"Third Counter = %lu", (unsigned long)counter);
}
}
调用:
- (void)viewDidLoad{
[super viewDidLoad];
[self firstCounter];
[self secondCounter];
[self thirdCounter];
}
输出:
First Counter = 0
... ...
First Counter = 999
Second Counter = 0
... ...
Second Counter = 999
Third Counter = 0
... ...
Third Counter = 999
你会看到第一个计时器运行完毕,然后是第二个计时器,最后是第三个计时器。也就是说这些循环是在同一个线程运行的。线程代码中被执行的每一块代码一直在运行,直到循 环结束。
使用多线程执行任务
贴:
- (void)viewDidLoad{
[super viewDidLoad];
// 开辟一个线程,执行任务
[NSThread detachNewThreadSelector:@selector(firstCounter)
toTarget:self
withObject:nil];
// 开辟一个线程,执行任务
[NSThread detachNewThreadSelector:@selector(secondCounter)
toTarget:self
withObject:nil];
// 该方法在主线程中执行
[self thirdCounter];
}
输出:
... ...
First Counter = 997
Second Counter = 984
First Counter = 998
Second Counter = 985
First Counter = 999
... ...
可以看到3个线程并行执行。
在后台创建一个线程来执行任务
贴:
[self performSelectorInBackground:@selector(firstCounter) withObject:nil];
[self performSelectorInBackground:@selector(secondCounter) withObject:nil];
[self performSelectorInBackground:@selector(thirdCounter) withObject:nil];
performSelectorInBackground方法为我们在后台创建了一个线程。这等同于 我们为 selectors 创建一个新的线程。 但是要记住,必须在调用的方法中加上自动释放池!
// 任务1
- (void) firstCounter{
@autoreleasepool {
// MyCode
}
}
来释放掉我们在操作过程中的内存!否则会发生内存泄漏!
对于使用线程的一些建议:
1.当我们需要中途停止线程时,我们不应该调用exit方法,而是调用cancel方法。因为,如果我们直接调用
exit方法的话,线程是直接退出,而没有机会去执行清理操作,可能会产生内存泄漏!
2.我们必须要清楚这么一个现象!
当线程在执行过程中,如果被sleepForTimeInterval后,线程将会被进入休眠。那么在它休眠期间又被cancel后,那么,事实上,线程在醒来后,任然会执行完它的操作。
还是贴给小代码:
线程方法:
// 线程执行
- (void) threadEntryPoint{
@autoreleasepool {
NSLog(@"Thread Entry Point");
while ([[NSThread currentThread] isCancelled] == NO){
[NSThread sleepForTimeInterval:10];
NSLog(@"Thread Loop");
}
NSLog(@"Thread Finished");
}
}
// 停止线程
- (void) stopThread{
NSLog(@"Cancelling the Thread");
[self.myThread cancel];
NSLog(@"Releasing the thread");
self.myThread = nil;
}
调用:
- (void)viewDidAppear:(BOOL)animated{
// 创建线程
self.myThread = [[NSThread alloc]
initWithTarget:self
selector:@selector(threadEntryPoint)
object:nil];
// 开启线程
[self.myThread start];
// 让线程3秒后取消
[self performSelector:@selector(stopThread) withObject:nil
afterDelay:3.0f];
}
输出:
Thread Entry Point
Cancelling the Thread
Releasing the thread
Thread Loop
Thread Finished
注意,输出的飘红部分,我明明调用了[NSThread sleepForTimeInterval:10];方法让线程进入休眠状态。并且让线程已经执行了stopThread方法中的[self.myThread cancel];方法把线程给取消了。但是,线程在被唤醒后,任然执行了后面的代码!
怎么办?!!!!兄弟们,这不科学啊!!!
说真的,我也不晓得怎么回事!这当然是一个很奇葩的问题!但是,在现实编程中,确实会遇到!
只有改良的办法:多加一层判断!!!
- (void) threadEntryPoint{
@autoreleasepool {
NSLog(@"Thread Entry Point");
while ([[NSThread currentThread] isCancelled] == NO){
[NSThread sleepForTimeInterval:10];
if ([[NSThread currentThread] isCancelled] == NO){
// 做一个改进,在需要执行的代码中,多加一层判断。
NSLog(@"Thread Loop");
}
}
NSLog(@"Thread Finished");
}
}
关于线程,就先搞到这里!
希望对你有所帮助!