iOS多线程开发(三)---Run Loop(四)

四,配置Run Loop源---配置源的过程就是源的创建调用过程

配置过程分为以下几个阶段---定义/创建(一个源)---安装(将输入源安装到所在Run Loop中)---注册(将输入源注册到客户端,协调输入源的客户端)---调用(通知输入源,开始工作)

4-1,定义自定义输入源

创建自定义输入源需要定义以下内容

1)输入源要处理的信息

2)使感兴趣的客户端知道如何和输入源交互的调度例程

3)处理其他任何客户发送请求的例程

4)使输入源失效的取消例程

Figure 3-2 Operating a custom input source

上图的处理流程:主线程(Main Thread)发起任务(Task)给工作线程(Worker Thread),主线程会给命令缓冲区(send command-->Command Buffer),通知输入源(signal source-->Input Source),并唤醒工作线程(Wake Up-->Worker Thread)。工作线程收到唤醒命令,Run Loop会调用输入源的处理程序,由它来执行命令缓冲区中相应的命令。

注:因为主线程和输入源所在工作线程都可以访问命令缓冲区(Command Buffer),因此这些访问必须使同步的

1)定义输入源(The custom input source object definition

下面代码中,定义了RunLoopSource对象,它管理命令缓冲区,并以此来接收其他线程的消息。RunLoopContext对象是一个用来传递RunLoopSource对象(RunLoopSource* source)和“run loop引用”(CFRunLoopRef runLoop)给程序主线程的一个容器

======

// Listing 3-3 The custom input source object definition

@interface RunLoopSource : NSObject

{

CFRunLoopSourceRef runLoopSource;

NSMutableArray* commands;

}

- (id)init;

- (void)addToCurrentRunLoop;

- (void)invalidate;

// handler method

- (void)sourecFired;

// Client interface for registering commands to process

- (void)addCommand:(NSInteger)command withData:(id)data;

- (void)fireAllCommandsOnRunLoop:(CFRunLoopRef)runLoop;

@end

// These are the CFRunLoopSourceRef callback functions.

void RunLoopSourceScheduleRoutine (void *info, CFRunLoopRef rl, CFStringRef mode);

void RunLoopSourcePerformRoutine (void *info);

void RunLoopSourceCancelRoutine (void *info, CFRunLoopRef rl, CFStringRef mode);

// RunLoopContext is a container object used during registration of the input source.

@interface RunLoopContext : NSObject

{

CFRunLoopRef runLoop;

RunLoopSource* source;

}

@property (readonly) CFRunLoopRef runLoop;

@property (readonly) RunLoopSource* source;

- (id)initWithSource:(RunLoopSource*)src andLoop:(CFRunLoopRef)loop;

@end

===当将输入源附加到run loop时,调用这个协调调度例程,将源注册到客户端(可以理解为其他线程)

// Listing 3-4 Scheduling a run loop source

//当source添加进runloop的时候,调用此回调方法 <== CFRunLoopAddSource(runLoop, source, mode);

void RunLoopSourceScheduleRoutine (void *info, CFRunLoopRef rl, CFStringRef mode)

{

RunLoopSource* obj = (RunLoopSource*)info;

AppDelegate* del = [AppDelegate sharedAppDelegate];

RunLoopContext* theContext = [[RunLoopContext alloc] initWithSource:obj andLoop:rl];

[del performSelectorOnMainThread:@selector(registerSource:) withObject:theContext  waitUntilDone:NO];

}

===在输入源被告知(signal source)时,调用这个处理例程,这儿只是简单的调用了 [obj sourceFired]方法

// Listing 3-5 Performing work in the input source

//当sourcer接收到消息的时候,调用此回调方法(CFRunLoopSourceSignal(source);CFRunLoopWakeUp(runLoop);

void RunLoopSourcePerformRoutine (void *info)

{

RunLoopSource* obj = (RunLoopSource*)info;

[obj sourceFired];

}

===如果使用CFRunLoopSourceInvalidate/CFRunLoopRemoveSource函数把输入源从run loop里面移除的话,系统会调用这个取消例程,并且把输入源从注册的客户端(可以理解为其他线程)里面移除

// Listing 3-6 Invalidating an input source ==

//当source 从runloop里删除的时候,调用此回调方法 <== CFRunLoopRemoveSource(runLoop, source, mode);

void RunLoopSourceCancelRoutine (void *info, CFRunLoopRef rl, CFStringRef mode)

{

RunLoopSource* obj = (RunLoopSource*)info;

AppDelegate* del = [AppDelegate sharedAppDelegate];

RunLoopContext* theContext = [[RunLoopContext alloc] initWithSource:obj andLoop:rl];

[del performSelectorOnMainThread:@selector(removeSource:) withObject:theContext  waitUntilDone:YES];

}

2)安装输入源到Run Loop---分两步首先初始化一个输入源,然后将这个输入源添加到当前Run Loop里面

// List 3-7 Installing the run loop source

- (id)init

{

/*

// Setup the context.

context.version = 0;

context.info = self;

context.retain = NULL;

context.release = NULL;

context.copyDescription = CFCopyDescription;

context.equal = CFEqual;

context.hash = CFHash;

context.schedule = RunLoopSourceScheduleRoutine;

context.cancel = RunLoopSourceCancelRoutine;

context.perform = RunLoopSourcePerformRoutine;

*/

CFRunLoopSourceContext context = {0, self, NULL, NULL, NULL, NULL, NULL,

&RunLoopSourceScheduleRoutine,

&RunLoopSourceCancelRoutine,

&RunLoopSourcePerformRoutine};

runLoopSource = CFRunLoopSourceCreate(NULL, 0, &context);

commands = [[NSMutableArray alloc] init];

return self;

}

- (void)addToCurrentRunLoop

{

CFRunLoopRef runLoop = CFRunLoopGetCurrent();

//Add the new CFRunLoopSourceRef to the indicated runloop, 并且回调RunLoopSourceScheduleRoutine函数

CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopDefaultMode);

}

3)协调输入源的客户端(将输入源注册到客户端)

输入源的主要工作就是将与输入源相关联的线程置于休眠状态,直到有事件发生。要达到这个目的,首先客户端(其他线程)知道有该输入源信息,并且有办法与之通信。

通知客户端关于这个输入源信息的方法之一,就是当该输入源开始安装到你的run loop上面后发送注册请求给相关的客户端,该输入源可以注册到任意数量的客户端

也可以通过由代理将输入源注册到感兴趣的客户端

===下面显示了应用委托(AppDelegate)定义的注册方法及从应用委托(AppDelegate)中移除的方法

- (void)registerSource:(RunLoopContext *)sourceInfo

{

NSMutableArray *sourceToPing;

[sourceToPing addObject:sourceInfo];

}

- (void)removeSource:(RunLoopContext *)sourceInfo

{

id objToRemove = nil;

NSMutableArray *sourceToPing;

for(RunLoopContext *context in sourceToPing)

{

if([context isEqual:sourceInfo])

{

objToRemove = context;

break;

}

}

if(objToRemove)

{

[sourceToPing removeObject:objToRemove];

}

}

注:上面两个函数分别在RunLoopSourceScheduleRoutine/RunLoopSourceCancelRoutine函数中被调用

4)通知输入源---客户端(其他线程)发数据到输入源,分两步首先发信号给输入源(signal source),然后唤醒输入源的run loop

===下面显示了客户端发送数据到输入源的方法,在本例中这个方法被放在RunLoopSource对象里面

// Listing 3-9 Waking up the run loop

- (void)fireAllCommandsOnRunLoop:(CFRunLoopRef)runLoop

{

//当手动调用此方法的时候,将会触发 RunLoopSourceContext的performCallback

CFRunLoopSourceSignal(runLoopSource);

CFRunLoopWakeUp(runLoop);

}

注:1,输入源就是一类事件(命令)处理机制。他是线程间的事件(命令)异步通讯机制,所以不能试图通过这个机制实现进程间的通讯。

2,因为CFRunLoopWakeUp函数不是信号安全的,所以对run loop的唤醒,不能在应用信号处理例程(RunLoopSourcePerformRoutine)里面使用。

4-2,配置定时源

配置源的过程其实是源在相关run loop的使用过程,包括定义(创建),安装(添加到相关run loop),注册(注册到其他需要交互的线程),以及使用四个过程。但是因为定时源在预设的时间点同步方式传递消息,是线程通知自己做某事情的一种方法,所以配置定时源,主要工作是创建,和安装。其他两个过程run loop自己就可以完成。

创建定时源有两种方式

===一种是使用NSTimer对象创建,一种是使用CFRunLoopTimerRef对象创建,及将创建的事例安装到Run Loop中

// Listing 3-10 Creating and scheduling timers using NSTimer

- (void)createAndScheduleTimerToRunLoopUsingNSTimer

{

// get the current run loop

NSRunLoop *myRunLoop = [NSRunLoop currentRunLoop];

// create and schedule the first timer  === 可以配置到不同的run loop模式

NSDate *futureDate = [NSDate dateWithTimeIntervalSinceNow:1.0];

NSTimer *myTimer = [[NSTimer alloc] initWithFireDate:futureDate interval:0.1 target:self selector:@selector(myDoFireTimer1:) userInfo:nil repeats:YES];

[myRunLoop addTimer:myTimer forMode:NSDefaultRunLoopMode];

// create and schedule the second timer === 只能在run loop的NSDefaultRunLoopMode下有效

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(myDoFireTimer2:) userInfo:nil repeats:YES];

}

// Listing 3-11 Creating and scheduling a timer using Core Foundation

- (void)createAndScheduleTimerToRunLoopUsingCFRunLoopTimerRef

{

// get the current run loop

CFRunLoopRef runLoop = CFRunLoopGetCurrent();

CFRunLoopTimerContext context = {0, NULL, NULL, NULL, NULL};

CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault, 0.1, 0.3, 0, 0, &myCFTimerCallBack, &context);

// add the CFRunLoopTimerRef to run loop kCFRunLoopCommonModes mode

CFRunLoopAddTimer(runLoop, timer, kCFRunLoopCommonModes);

}

4-2,配置基于端口的输入源

iOS系统提供了基于端口的输入源对象,用以线程或进程间通讯

1)配置NSMachPort对象---本地线程间通信,通过传递端口对象变量进行端口间通讯

基本机制:A线程(父线程)创建NSMachPort对象,并加入A线程的run loop。当创建B线程(辅助线程)时,将创建的NSMachPort对象传递到主体入口点,B线程(辅助线程)就可以使用相同的端口对象将消息传回A线程(父线程)。

A,实现A线程(父线程)的代码

===在下面代码中,创建一个NSPort对象,并把这个端口对象安装(add)到线程的Run Loop里面,同时创建一个新的线程,并把NSPort对象作为参数传入到新线程的主体入口点

// Listing 3-12 Main thread launch sub-thread method

- (void)lanchThread

{

NSPort *myPort = [NSPort port];

if(myPort)

{

// This class handles incoming port message

[myPort setDelegate:self];

// install the port as an input source

[[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode];

// Detach the thread.Let the worker release the port--加载一个子线程

[NSThread detachNewThreadSelector:@selector(LaunchThreadWithPort:) toTarget:[MyWorkerThread Class] withObject:myPort];

}

}

===NSPort是通过代理模式传送消息,下面这段代码是NSPortDelegate的代理方法,用以从B线程回传消息((NSPortMessage *)message)

#pragma mark

#define kCheckinMessage     100

#pragma mark NSPortDelegate Method

// This is the NSPort Delegate Method

// It handle responses from the worker thread(B线程)

- (void)handlePortMessage:(NSPortMessage *)message

{

uint32_t mssgId = [message msgid];

NSPort *distantPort = nil;

if(message == kCheckinMessage)

{

// get the worker thread‘s communication port

distantPort = [message sendPort];

// Retain and save the worker port for later use

[self storeDistantPort:distantPort];

}

else

{

// Handle other message

......

}

}

B,B线程(辅助线程)的实现代码

===下面是辅助线程的类方法,里面创建了辅助线程实例,并把传入的NSPort保存下来。同时,通过NSMachPort发送一个Check-In Message(NSPortMessage类型,在这个Message类型中设置了SendPort/ReceivePort,链接这两个端口)给A线程。

// Listing 3-14 Launching the worker thread using Mach ports

+ (void)LaunchThreadWithPort:(id)inData

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// set up the connection between this thread and the main thread

NSPort *distantPort = (NSPort *)inData;

MyWorkerThread *workObj = [[self alloc] init];

[workObj sendCheckinMessage:distantPort];

[distantPort release];

// Let the run loop process things

do

{

}while (![workerObj shouldExit]);

[workObj release];

[pool release];

}

// Listing 3-15 Sending the check-in message using Mach ports

- (void)sendCheckinMessage:(NSPort *)outPort

{

// Retain and save the remote port for future use

[self setRemotePort:outPort]; // set NSPort *remotePort;

// create and configure the worker thread port

NSPort *myPort = [NSMachPort port];

[myPort setDelegate:self];

[[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode];

// create the check-in message

NSPortMessage *messageObj = [[NSPortMessage alloc] initWithSendPort:outPort receivePort:myPort components:nil];

if(messageObj)

{

// Finish configuring the message and send it immediately

[messageObj setMsgId:setMsgid:kCheckinMessage];

[messageObj sendBeforeDate:[NSDate date];

}

}

===注:最终,B线程NSMachPort)端口传递消息给A线程的(NSPort)端口(handlePortMessage代理方法)。

 

2)配置NSMessagePort对象

===只能在一个设备内程序间通信,不能在不同设备间通信。将端口名称注册到NSMessagePortNameServer里面,其他线程通过这个端口名称从NSMessagePortNameServer来获取这个端口对象。

// Listing 3-9 Waking up the run loop

- (void)fireAllCommandsOnRunLoop:(CFRunLoopRef)runLoop

{

//当手动调用此方法的时候,将会触发 RunLoopSourceContext的performCallback

CFRunLoopSourceSignal(runLoopSource);

CFRunLoopWakeUp(runLoop);

NSPort *localPort = [[NSMessagePort alloc] init];

// configure the port and add it to the current run loop

[localPort setDelegate:self];

[[NSRunLoop currentRunLoop] addPort:localPort forMode:NSDefaultRunLoopMode];

// register the port using the specific name, and The name is unique

NSString *localPortName = [NSString stringWithFormat:@"MyPortName"];

// there is only NSMessagePortNameServer in the mac os x system

//[[NSMessagePortNameServer sharedInstance] registerPort:localPort name:localPortName];

}

3)在Core Fundation中配置基于端口的源

CFMessagePortRef---实现本地设备内程序间通讯。CFMessagePort objects provide a communications channel that can transmit arbitrary data between multiple threads or processes on the local machine.

You create a local message port with CFMessagePortCreateLocal and make it available to other processes by giving it a name, either when you create it or later with CFMessagePortSetName. Other processes then connect to it using CFMessagePortCreateRemote, specifying the name of the port.

To listen for messages, you need to create a run loop source with CFMessagePortCreateRunLoopSource and add it to a run loop with CFRunLoopAddSource.

Important: If you want to tear down the connection, you must invalidate the port (using CFMessagePortInvalidate) before releasing the runloop source and the message port object.

Your message port’s callback function will be called when a message arrives. To send data, you store the data in a CFData object and call CFMessagePortSendRequest. You can optionally have the function wait for a reply and return the reply in another CFData object.

Message ports only support communication on the local machine. For network communication, you have to use a CFSocket object.

Functions by Task Creating a CFMessagePort Object

* CFMessagePortCreateLocal---监听线程创建监听端口,Returns a local CFMessagePort object. * CFMessagePortCreateRemote---工作线程用来获取监听线程的端口对象,Returns a CFMessagePort object connected to a remote port.

Configuring a CFMessagePort Object

* CFMessagePortCreateRunLoopSource * CFMessagePortSetInvalidationCallBack * CFMessagePortSetName

Using a Message Port

* CFMessagePortInvalidate * CFMessagePortSendRequest---工作线程给监听端口发送请求

Examining a Message Port

* CFMessagePortGetContext * CFMessagePortGetInvalidationCallBack * CFMessagePortGetName * CFMessagePortIsRemote * CFMessagePortIsValid

Getting the CFMessagePort Type ID

* CFMessagePortGetTypeID

===主线程代码,创建CFMessagePortRef本地端口作为监听端口,并注册到当前run loop。MainThreadResponseHandler函数是消息回调函数,当有消息从工作线程传递过来时将调用这个函数

// Listing 3-17 Attaching a Core Foundation message port to a new thread

#define kThreadStackSize (8 *4096)

void MySpawnThread( void )

{

// Create a local port for receiving responses.

CFStringRef myPortName;

CFMessagePortRef myPort;

CFRunLoopSourceRef rlSource;

CFMessagePortContext context = {0, NULL, NULL, NULL, NULL};

Boolean shouldFreeInfo;

// create a string for the port name

myPortName = CFStringCreateWithFormat(NULL, NULL, CFSTR("com.myapp.MainThread"));

// create the port

myPort = CFMessagePortCreateLocal(NULL, myPortName, &MainThreadResponseHandler, &context, &shouldFreeInfo);

if(myPort != NULL)

{// The port was successfully created

// Now create a run loop source

rlSource = CFMessagePortCreateRunLoopSource(NULL, myPort, 0);

if(rlSource != NULL)

{

// add the source to the current run loop

CFRunLoopAddSource(CFRunLoopGetCurrent(), rlSource, kCFRunLoopDefaultMode);

// once installed, these can be freed.

CFRelease(myPort);

CFRelease(rlSource);

}

}

// create the thread and continue processing

NSThread *thread = [[NSThread alloc] initWithTarget:[MyThreadClass Class] selector:@selector(ServerThreadEntryPoint:) object:@"com.myapp.MainThread"];

[thread setStackSize:kThreadStackSize];

[thread start];

}

// Listing 3-18 Receiving the checkin me

#define kCheckinMessage 100

CFDataRef MainThreadResponseHandler(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void*info)

{

if(msgid == kCheckinMessage)

{

CFStringRef threadPortName;

CFIndex bufferLength = CFDataGetLength(data);

UInt8* buffer = CFAllocatorAllocate(NULL, bufferLength, 0);

CFDataGetBytes(data, CFRangeMake(0, bufferLength), buffer);

threadPortName = CFStringCreateWithBytes(NULL, buffer, bufferLength,kCFStringEncodingASCII, FALSE);

#if 0

CFMessagePortRef messagePort;

// You must obtain a remote message port by name for future reference

messagePort = CFMessagePortCreateRemote(NULL, threadPortName);

if(messagePort)

{

// Retain and save the thread‘s com port for future reference

AddPortToListOfActiveThreads(messagePort);

// Since the port is retained by the previous function, release it here

CFRelease(messagePort);

}

#endif

// clean up

CFRelease(threadPortName);

CFAllocatorDeallocate(NULL, buffer);

}

else

{

// handle other messages

}

return NULL;

}

===工作线程代码,获取主线程端口,通过CFMessagePortSendRequest传递消息到主线程端口

// Listing 3-19 Setting up the thread structures

+ (void)ServerThreadEntryPoint:(NSString *)name

{

// create the remote port to main thread

CFMessagePortRef mainThreadPort;

CFStringRef portName = (CFStringRef)name;

mainThreadPort = CFMessagePortCreateRemote(NULL, portName);

#if 1

// Create a port for the worker thread.

CFStringRef myPortName = CFStringCreateWithFormat(NULL, NULL, CFSTR("com.MyApp.Thread-%d"),CFRunLoopGetTypeID());

//  Store  the  port  in  this  thread’s  context  info  for  later  reference.

CFMessagePortContext context = {0, mainThreadPort, NULL, NULL, NULL};

Boolean shouldFreeInfo;

Boolean shouldAbort = TRUE;

CFMessagePortRef myPort = CFMessagePortCreateLocal(NULL, myPortName, &ProcessClientRequest, &context, &shouldFreeInfo);

if(!shouldFreeInfo)

{

CFRunLoopSourceRef rlSource = CFMessagePortCreateRunLoopSource(NULL, myPort, 0);

if(rlSource)

{

// Add the source to the current run loop.

CFRunLoopAddSource(CFRunLoopGetCurrent(), rlSource, kCFRunLoopDefaultMode);

// Once installed, these can be freed.

CFRelease(myPort);

CFRelease(rlSource);

// Package up the port name and send the check-in message.

CFDataRef returnData = nil;

CFDataRef outData;

CFIndex stringLength = CFStringGetLength(myPortName);

UInt8* buffer = CFAllocatorAllocate(NULL, stringLength, 0);

CFStringGetBytes(myPortName, CFRangeMake(0,stringLength), kCFStringEncodingASCII, 0, false, buffer, stringLength, NULL);

outData = CFDataCreate(NULL, buffer, stringLength);

CFMessagePortSendRequest(mainThreadPort, kCheckinMessage, outData, 0.1, 0.0, NULL, &returnData);

// Clean up thread data structures.

CFRelease(outData);

CFAllocatorDeallocate(NULL, buffer);

// Enter the run loop.

CFRunLoopRun();

}

}

#endif

}

时间: 2024-10-26 17:32:33

iOS多线程开发(三)---Run Loop(四)的相关文章

ios 多线程开发(三)Run Loops

Run loops是线程相关的一些基本东西.一个run loop是一个处理消息的循环.用来处理计划任务或者收到的事件.run loop的作用是在有事做的时候保持线程繁忙,没事的时候让线程挂起. Run loop的管理并不是完全自动的.你仍然需要设计代码来在合适的时候启动run loop来相应事件.Cocoa和Core Foundation都提供了run loop对象来配置和管理run loop.程序并不需要创建这些对象,每个线程,包括主线程都有一个对应的run loop对象.只有非主线程需要明确

iOS多线程开发——NSThread浅析

在IOS开发中,多线程的实现方式主要有三种,NSThread.NSOperation和GCD,我前面博客中对NSOperation和GCD有了较为详细的实现,可以参考<iOS多线程开发--NSOperation/NSOperationQueue浅析><iOS多线程开发--GCD的使用与多线程开发浅析>.以及对于多线程中的同步异步,并行串行等概念,我在<GCD实践--串行队列/并发队列与iOS多线程详解>中也有较为详细的讲解.为了学习的完整性,今天我们主要从代码层面来实现

iOS多线程的初步研究(四)-- NSTimer

 iOS多线程的初步研究(四)-- NSTimer 原文地址  http://www.cnblogs.com/sunfrog/p/3243230.html 理解run loop后,才能彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的. 先看看NSTimer的两个常用方法: + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelec

iOS多线程开发之深入GCD

iOS多线程开发之深入GCD 一.前言 在以前的一些系列博客中,对iOS中线程的管理做了总结,其中涵盖了GCD的相关基础知识:http://my.oschina.net/u/2340880/blog/417746.那里面将GCD的线程管理能力,列队组能力,通过信号和消息控制程序流程的能力都有介绍,这里,我们继续深入GCD的功能,通过GCD来处理一些逻辑更加复杂的代码功能. 二.延时追加任务 当我们在程序中处理延时任务的时候,我们一般会通过两种方式,一种是通过定时器进行延时执行,另外一种是通过如下

(转发)IOS高级开发~Runtime(四)

用C代替OC: #import <objc/runtime.h> #import <objc/message.h> #import <stdio.h> extern int UIApplicationMain (int argc,char *argv[],void *principalClassName,void *delegateClassName); struct Rect { float x; float y; float width; float height;

IOS多线程开发

本文转载至 http://blog.csdn.net/davidsph/article/details/8171607 IOS的多线程,一般分为三种方式: 1,Thread;2, Cocoa operations;3, Grand Central Dispatch (GCD) (iOS4 才开始支持) 下面简单说明一下: 1:NSThread   创建方式主要有两种: [NSThread detachNewThreadSelector:@selector(myThreadMainMethod:)

iOS多线程开发——GCD的使用与多线程开发浅析(二)

对于iOS多线程开发,我们时刻处于学习之中,在看书中,看文档中,项目开发中,都可以去提高自己.最近刚看完了<Objective-C高级编程 iOS与OS X多线程和内存管理>这本书后,对多线程有了更为深入的理解,故在此做一个总结与记录.这本书我已经上传至网盘  https://pan.baidu.com/s/1c2fX3EC ,这本书是iOS开发者必读的书之一,写得很不错,欢迎大家下载阅读.书的封面如下,故也称狮子书: . (1)多线程会遇到的问题 . 多线程会出现什么问题呢?当多个线程对同一

iOS多线程开发小demo

首先演示一下主线程的阻塞 // DYFViewController.m // 623-01-阻塞多线程 // // Created by dyf on 14-6-23. // Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. // #import "DYFViewController.h" @interface DYFViewController () @end @implementation DYFViewCon

iOS多线程开发小demo2,NSThread篇

用NSThread创建子线程的3种方法 // DYFViewController.m // 623-02-pthread // // Created by dyf on 14-6-23. // Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. // #import "DYFViewController.h" #import <pthread.h> @interface DYFViewController

学习 iOS多线程开发 Demo示意

并发所描述的概念就是同时运行多个任务.这些任务可能是以在单核 CPU 上分时(时间分享)的形式同时运行,也可能是在多核 CPU 上以真正的并行方式来运行.这篇文章是作者在学习iOS开发技术当中,遇到多线程问题时捋顺思路时的一些看法. GCD是iOS开发当中解决多核开发的一个技术. 主要有三种队列:一.运行在主线程的 Main queque   通过dispatch_get_main_queque 来获取 二.并行队列 global dispatch queque ,通过dispatch_get_