NSThread的使用
NSThread 有兩種直接建立方式:
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
第一個是執行個體方法,第二個是類方法
1、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
2、NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(doSomething:)
object:nil];
[myThread start];
參數的意義:
selector :線程執行的方法,這個selector隻能有一個參數,而且不能有傳回值。
target :selector消息發送的對象
argument:傳輸給target的唯一參數,也可以是nil
第一種方式會直接建立線程并且開始運作線程,第二種方式是先建立線程對象,然後再運作線程操作,在運作線程操作前可以設定線程的優先級等線程資訊
不顯式建立線程的方法:
用NSObject的類方法 performSelectorInBackground:withObject: 建立一個線程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];
下載下傳圖檔的例子:
初始化圖檔連結:
#define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"
初始化UIImageView:
self.imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.imageView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.imageView];
[NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];
更新ui:
-(void)downloadImage:(NSString *) url{
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [[UIImage alloc]initWithData:data];
if(image == nil)
{
}else
{
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
}
-(void)updateUI:(UIImage*) image
{
self.imageView.image = image;
}
線程下載下傳完圖檔後怎麼通知主線程更新界面呢?
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
performSelectorOnMainThread是NSObject的方法,除了可以更新主線程的資料外,還可以更新其他線程的比如:
用:performSelector:onThread:withObject:waitUntilDone:
線程同步
我們示範一個經典的賣票的例子來講NSThread的線程同步:
.h檔案:
@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
int tickets;
int count;
NSThread* ticketsThreadone;
NSThread* ticketsThreadtwo;
NSCondition* ticketsCondition;
NSLock *theLock;
}
.m檔案:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
tickets = 100;
count = 0;
theLock = [[NSLock alloc] init];
// 鎖對象
ticketsCondition = [[NSCondition alloc] init];
ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[ticketsThreadone setName:@"Thread-1"];
[ticketsThreadone start];
ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[ticketsThreadtwo setName:@"Thread-2"];
[ticketsThreadtwo start];
self.rootViewController = [[RootViewController alloc]init];
[self.window setRootViewController:self.rootViewController];
[self.window addSubview:self.rootViewController.view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)run
{
while (TRUE)
{
// 上鎖
// [ticketsCondition lock];
[theLock lock];
if(tickets >= 0){
[NSThread sleepForTimeInterval:0.09];
count = 100 - tickets;
NSLog(@"目前票數是:%d,售出:%d,線程名:%@",tickets,count,[[NSThread currentThread] name]);
tickets--;
}else{
break;
}
[theLock unlock];
// [ticketsCondition unlock];
}
}
其他同步
我們可以使用指令 @synchronized 來簡化 NSLock的使用,這樣我們就不必顯示編寫建立NSLock,加鎖并解鎖相關代碼。
- (void)doSomeThing:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}
還有其他的一些鎖對象,比如:循環鎖NSRecursiveLock,條件鎖NSConditionLock,分布式鎖NSDistributedLock等等,可以自己看官方文檔學習
著作權聲明:本文由http://blog.csdn.net/totogo2010/原創,歡迎轉載分享。請尊重作者勞動,轉載時保留該聲明和作者部落格連結,謝謝!