多線程
程式:由源代碼生成的可執行應用。
程序:一個正在運作的程式可用看做一個程序,程序擁有獨立運作所需要的全部資源。
線程:程式中獨立運作的代碼段
iOS5之後子線程也有重新整理UI的能力,但不夠快
iOS中關于UI的添加和重新整理必須在主線程中操作
使用多線程開發的優點:資源使用率更好,程式設計在某些情況下更簡單,程式響應更快
缺點:盡管提升了性能,但是存在一些通路限制,比如線程同步、線程互斥等,多線程在使用的時候,最終是要回到主線程重新整理UI,如果開辟過多的多線程,會造成CPU的消耗
一、NSThread
每個線程都維護着自己對應的NSAutoreleasePool對象,将其放線上程棧的棧頂。當線程結束時會情況自動釋放池
在應用程式打開的是,系統會自動為主線程建立一個自動釋放池
我們手動建立的子線程需要我們手動添加自動釋放池
//1.輕量級别的多線程實作方式
//當使用alloc init方式,需要我們手動啟動,如果使用便利構造器的方法,不需要手動啟動
//object 是線程回調方法的參數,不需要就寫nil
NSThread *forThread = [[NSThread alloc]initWithTarget:self selector:@selector(aHundredMillion) object:nil];
//通過便利構造器的方法建立Thread對象,不用手動啟動
[NSThread detachNewThreadSelector:@selector(thread_1Action:) toTarget:self withObject:@"thread_1"];
//為forThread命名
forThread.name = @"老二";
//線程優先級,當優先級越高,線程被先執行的機率越高,0~1.0越來越高
forThread.threadPriority = 1.0;
//啟動線程
[forThread start];
//得到目前線程的資訊
NSLog(@"iamgeThread--%@",[NSThread currentThread]);
//得到主線程的資訊
NSLog(@"%@",[NSThread mainThread]);
//線程休眠
[NSThread sleepForTimeInterval:2];
//結束線程
//1.給線程發結束消息
<p>[forThread cancel];</p>//2.了解結束線程
[NSThread exit];
//判斷線程是否在執行
[forThread isExecuting];
//判斷線程是否執行完畢
[forThread isFinished];
<p>NSObject的多線程方法</p><pre name="code" class="objc"> //1.從主線程進入子線程
[self performSelectorInBackground:@selector(objectThreadAction:) withObject:@"object開的子線程"];
//NSObject進入子線程
-(void)objectThreadAction:(NSString*)sender
{
NSLog(@"%@",sender);
NSLog(@"%@",[NSThread currentThread]);
//從子線程回到主線程
//waitUnitDone:YES隻有回主線程的回調方法執行結束才會執行下面的操作。NO:與之相反
[self performSelectorOnMainThread:@selector(backMainThread) withObject:nil waitUntilDone:YES];
NSLog(@"在回到主線程的底下");
}
線程鎖
@property (nonatomic,retain)NSLock *myLock;//線程鎖,當多個線程同時通路同一資源的時候,對資源進行保護
@property (nonatomic,assign)int ticket_Sum;//線程直接跳的總數
@end
@implementation ViewController
-(NSLock *)myLock
{
if (!_myLock) {
_myLock = [[NSLock alloc]init];
}
return _myLock;
}
//線程鎖學習
-(void)lock_study
{
@synchronized(self) {
//線程鎖,保證目前隻有一個線程在通路該資源
//将需要加鎖保護的代碼寫在花括号内
}
//當線程通路的是,加線程鎖
[self.myLock lock];
while (true) {
if (_ticket_Sum > 0)
{
_ticket_Sum--;
NSLog(@"剩餘票=== %d",_ticket_Sum);
}
else
{
break;
}
}
//當正在執行的線程執行完操作的時候,解鎖。其他線程可以通路
[self.myLock unlock];
}
二、NSOperation
NSOperation類,在MVC中屬于M,是用來封裝單個任務的相關代碼和資料的抽象類。
因為它是抽象的,不能直接使用這個類,而使用子類(NSInvocationOperation或NSBlockOperation)來執行任務。
NsOperation,隻是一個操作,本身無主線程子線程之分,可以在任意線程中使用,通常與NSOperationQueue結合使用
-(void)operation
{
//初始化一個任務 target-action
NSInvocationOperation *invocation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invocationAction:) object:@"參數"];
//當任務不在隊列中,需要手動啟動
[invocation start];
//操作block的方法
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
//實作我們需要做的操作
NSLog(@"block 目前線程---%@",[NSThread currentThread]);
}];
//為block操作添加多個block執行
//當使用addExecutionBlock添加可執行的block時,這些block會在目前線程或者其他子線程中進行
for (int i = 0; i < 10; i++) {
[blockOperation addExecutionBlock:^{
NSLog(@"block2 目前線程-- %@",[NSThread currentThread]);
}];
}
//最後執行的block,此block會在最後執行
blockOperation.completionBlock = ^()
{
NSLog(@"最後執行的block-------%@",[NSThread currentThread]);
};
//all block must be before start
//啟動操作
[blockOperation start];
NSLog(@"我在最下面");
}
把任務加入隊列當中
//隊列quene NSOperationQuene是對GCD的OC級别的封裝
-(void)operationQuene
{
//先初始化隊列的對象,(其他隊列:出了主隊列,人為初始化的隊列都是其他隊列)
NSOperationQueue *otherQuene = [[NSOperationQueue alloc]init];
//設定最大并發數,預設為-1,可以無限個,設定為1的時候,在同一時刻隻能執行一個操作
otherQuene.maxConcurrentOperationCount = 10;
for (int i = 0; i < 10; i++) {
//建立可執行的操作對象
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"隊列-----目前線程---%@--%d",[NSThread currentThread],i);
}];
if (i == 3) {
}
//将block操作添加到隊列中,當操作對象添加到隊列中之後,就不需要手動啟動了
[otherQuene addOperation:blockOperation];
}
NSBlockOperation *blockOperation_0 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"隊列-----目前線程---%@--%d",[NSThread currentThread],0);
}];
NSBlockOperation *blockOperation_1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"隊列-----目前線程---%@--%d",[NSThread currentThread],1);
}];
NSBlockOperation *blockOperation_2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"隊列-----目前線程---%@--%d",[NSThread currentThread],2);
}];
NSBlockOperation *blockOperation_3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"隊列-----目前線程---%@--%d",[NSThread currentThread],3);
}];
NSBlockOperation *blockOperation_4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"隊列-----目前線程---%@--%d",[NSThread currentThread],4);
}];
//為事件添加依賴關系,第四個必須在第三個後面執行,這樣第四個任務一定在第三個執行後,才會執行
//要先添加依賴再講事件添加到隊列
[blockOperation_4 addDependency:blockOperation_3];
//添加進隊列
[otherQuene addOperation:blockOperation_0];
[otherQuene addOperation:blockOperation_1];
[otherQuene addOperation:blockOperation_2];
[otherQuene addOperation:blockOperation_3];
[otherQuene addOperation:blockOperation_4];
}
添加到主隊列
//主隊列
-(void)operationMainQuene
{
NSLog(@"目前線程--與主隊列無關--%@",[NSThread currentThread]);
NSOperationQueue *mainQuene = [NSOperationQueue mainQueue];
for (int i = 0; i < 10; i++) {
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"主線程-----%@-------%d",[NSThread currentThread],i);
}];
[mainQuene addOperation:blockOperation];
}
}
GCD 多線程優化 這個下一篇再說吧