iOS__多線程

iOS多線程 之NSThread的使用

1、簡介:
1.1 iOS有三種多線程編程的技術锚烦,分別是:
1.、NSThread
2帝雇、Cocoa NSOperation (iOS多線程編程之NSOperation和NSOperationQueue的使用)
3涮俄、GCD 全稱:Grand Central Dispatch( iOS多線程編程之Grand Central Dispatch(GCD)介紹和使用)

這三種編程方式從上到下,抽象度層次是從低到高的摊求,抽象度越高的使用越簡單禽拔,也是Apple最推薦使用的。
這篇我們主要介紹和使用NSThread室叉,后面會繼續(xù)2睹栖、3 的講解和使用。

1.2 三種方式的有缺點介紹:

NSThread:
優(yōu)點:NSThread 比其他兩個輕量級
缺點:需要自己管理線程的生命周期茧痕,線程同步野来。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷
NSThread實現(xiàn)的技術有下面三種:

Technology
Description
Cocoa threads
Cocoa implements threads using the NSThread class.
Cocoa also provides methods on NSObject for spawning new threads and executing code on already-running threads.
For more information, see “Using NSThread” and “Using NSObject to Spawn a Thread.”
POSIX threads
POSIX threads provide a C-based interface for creating threads.
If you are not writing a Cocoa application, this is the best choice for creating threads.
The POSIX interface is relatively simple to use and offers ample flexibility for configuring your threads.
For more information, see “Using POSIX Threads”
Multiprocessing Services
Multiprocessing Services is a legacy C-based interface used by applications transitioning from older versions of Mac OS.
This technology is available in OS X only and should be avoided for any new development.
Instead, you should use the NSThread class or POSIX threads.
If you need more information on this technology, see Multiprocessing Services Programming Guide.
一般使用cocoa thread 技術。

Cocoa operation

優(yōu)點:不需要關心線程管理踪旷,數(shù)據(jù)同步的事情曼氛,可以把精力放在自己需要執(zhí)行的操作上豁辉。
Cocoa operation相關的類是NSOperation ,NSOperationQueue舀患。
NSOperation是個抽象類徽级,使用它必須用它的子類,可以實現(xiàn)它或者使用它定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation聊浅。
創(chuàng)建NSOperation子類的對象餐抢,把對象添加到NSOperationQueue隊列里執(zhí)行。

GCD

Grand Central Dispatch (GCD)是Apple開發(fā)的一個多核編程的解決方法低匙。在iOS4.0開始之后才能使用旷痕。GCD是一個替代諸如NSThread, NSOperationQueue, NSInvocationOperation等技術的很高效和強大的技術。現(xiàn)在的iOS系統(tǒng)都升級到6了顽冶,所以不用擔心該技術不能使用欺抗。

介紹完這三種多線程編程方式,我們這篇先介紹NSThread的使用强重。
2绞呈、NSThread的使用
2.1 NSThread 有兩種直接創(chuàng)建方式:

(id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
(void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
第一個是實例方法,第二個是類方法
[cpp] view plaincopy

1竿屹、[NSThread detachNewThreadSelector:@selector(doSomething:) 
toTarget:self withObject:nil];
2报强、NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(doSomething:)
object:nil];
[myThread start];
2.2參數(shù)的意義:

selector :線程執(zhí)行的方法,這個selector只能有一個參數(shù)拱燃,而且不能有返回值秉溉。
target :selector消息發(fā)送的對象
argument:傳輸給target的唯一參數(shù),也可以是nil
第一種方式會直接創(chuàng)建線程并且開始運行線程碗誉,第二種方式是先創(chuàng)建線程對象召嘶,然后再運行線程操作,在運行線程操作前可以設置線程的優(yōu)先級等線程信息
2.3 PS:不顯式創(chuàng)建線程的方法:

用NSObject的類方法 performSelectorInBackground:withObject: 創(chuàng)建一個線程:
[Object performSelectorInBackground:@selector(doSomething) 
withObject:nil];
2.4 下載圖片的例子:
2.4.1 新建singeView app
新建項目哮缺,并在xib文件上放置一個imageView控件弄跌。按住control鍵拖到viewControll

er.h文件中創(chuàng)建imageView IBOutlet
ViewController.m中實現(xiàn):
[cpp] view plaincopy

//
// ViewController.m
// NSThreadDemo
//
// Created by rongfzh on 12-9-23.
// Copyright (c) 2012年 rongfzh. All rights reserved.
//

import "ViewController.h"
define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"
@interface ViewController ()

@end

@implementation ViewController

-(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;
}

(void)viewDidLoad
{
[super viewDidLoad];
// [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];
[thread start];
}

(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
2.4.2線程間通訊

線程下載完圖片后怎么通知主線程更新界面呢?

[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];

performSelectorOnMainThread是NSObject的方法尝苇,除了可以更新主線程的數(shù)據(jù)外铛只,還可以更新其他線程的比如:
用:performSelector:onThread:withObject:waitUntilDone:
運行下載圖片:

圖片下載下來了。

2.3 線程同步

我們演示一個經(jīng)典的賣票的例子來講NSThread的線程同步:
.h

[cpp] view plaincopy

import <UIKit/UIKit.h>
@class ViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
int tickets;
int count;
NSThread ticketsThreadone;
NSThread ticketsThreadtwo;
NSCondition ticketsCondition;
NSLock theLock;
}
@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ViewController *viewController;

@end

[cpp] view plaincopy

(BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions
{

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.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
// Override point for customization after application launch.  
self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];  
self.window.rootViewController = self.viewController;  
[self.window makeKeyAndVisible];  
return YES;
}
-(void)run {
while (TRUE) {
  // 上鎖
// [ticketsCondition lock];
  [theLock lock];  
  if(tickets >= 0) {  
      [NSThread sleepForTimeInterval:0.09];  
      count = 100 - tickets;  
      NSLog(@"當前票數(shù)是:%d,售出:%d,線程名:%@",tickets,count,[[NSThread currentThread] name]);  
      tickets--;  
  } else {  
      break;  
  }  
  [theLock unlock];
// [ticketsCondition unlock];
}
}

如果沒有線程同步的lock糠溜,賣票數(shù)可能是-1.加上lock之后線程同步保證了數(shù)據(jù)的正確性淳玩。
上面例子我使用了兩種鎖,一種NSCondition 非竿,一種是:NSLock蜕着。 NSCondition我已經(jīng)注釋了。

線程的順序執(zhí)行
他們都可以通過
[ticketsCondition signal]; 發(fā)送信號的方式红柱,在一個線程喚醒另外一個線程的等待承匣。
比如:
[cpp] view plaincopy

import "AppDelegate.h"
import "ViewController.h"
@implementation AppDelegate

(BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions
{

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];

NSThread *ticketsThreadthree = [[NSThread alloc] initWithTarget:self selector:@selector(run3) object:nil];
[ticketsThreadthree setName:@"Thread-3"];
[ticketsThreadthree start];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}

-(void)run3{
while (YES) {
[ticketsCondition lock];
[NSThread sleepForTimeInterval:3];
[ticketsCondition signal];
[ticketsCondition unlock];
}
}

(void)run{
while (TRUE) {
  // 上鎖  
  [ticketsCondition lock];  
  [ticketsCondition wait];  
  [theLock lock];  
  if(tickets >= 0){  
      [NSThread sleepForTimeInterval:0.09];  
      count = 100 - tickets;  
      NSLog(@"當前票數(shù)是:%d,售出:%d,線程名:%@",tickets,count,[[NSThread currentThread] name]);  
      tickets--;  
  }else{  
      break;  
  }  
  [theLock unlock];  
  [ticketsCondition unlock];
}
}

wait是等待蓖乘,我加了一個 線程3 去喚醒其他兩個線程鎖中的wait
其他同步
我們可以使用指令 @synchronized 來簡化 NSLock的使用,這樣我們就不必顯示編寫創(chuàng)建NSLock,加鎖并解鎖相關代碼韧骗。

(void)doSomeThing:(id)anObj
{
@synchronized(anObj)
{
  // Everything between the braces is protected
 by the @synchronized directive.
}
}

還有其他的一些鎖對象嘉抒,比如:循環(huán)鎖NSRecursiveLock,條件鎖NSConditionLock袍暴,分布式鎖NSDistributedLock等等,可以自己看官方文檔學習
一種是用定義好的兩個子類:
NSInvocationOperation 和 NSBlockOperation众眨。
另一種是繼承NSOperation

如果你也熟悉Java,NSOperation就和java.lang.Runnable接口很相似容诬。和Java的Runnable一樣,NSOperation也是設計用來擴展的沿腰,只需繼承重寫NSOperation的一個方法main览徒。相當與java 中Runnalbe的Run方法。然后把NSOperation子類的對象放入NSOperationQueue隊列中颂龙,該隊列就會啟動并開始處理它习蓬。

NSInvocationOperation例子:

實現(xiàn)代碼如下:

[cpp] view plaincopy

import "ViewController.h"
define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"
@interface ViewController ()

@end

@implementation ViewController

(void)viewDidLoad
{
[super viewDidLoad];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self

                                                                     selector:@selector(downloadImage:)  
                                                                       object:kURL];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:operation];
// Do any additional setup after loading the view, typically from a nib.
}

-(void)downloadImage:(NSString )url{
NSLog(@"url:%@", url);
NSURL nsUrl = [NSURL URLWithString:url];
NSData data = [[NSData alloc]initWithContentsOfURL:nsUrl];
UIImage image = [[UIImage alloc]initWithData:data];
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
-(void)updateUI:(UIImage*) image{
self.imageView.image = image;
}

viewDidLoad方法里可以看到我們用NSInvocationOperation建了一個后臺線程,并且放到NSOperationQueue中措嵌。后臺線程執(zhí)行downloadImage方法躲叼。
downloadImage 方法處理下載圖片的邏輯。下載完成后用performSelectorOnMainThread執(zhí)行主線程updateUI方法企巢。
updateUI 并把下載的圖片顯示到圖片控件中枫慷。
運行可以看到下載圖片顯示在界面上。

第二種方式繼承NSOperation

在.m文件中實現(xiàn)main方法浪规,main方法編寫要執(zhí)行的代碼即可或听。

如何控制線程池中的線程數(shù)?

隊列里可以加入很多個NSOperation, 可以把NSOperationQueue看作一個線程池笋婿,可往線程池中添加操作(NSOperation)到隊列中誉裆。線程池中的線程可看作消費者,從隊列中取走操作缸濒,并執(zhí)行它足丢。

通過下面的代碼設置:

[queue setMaxConcurrentOperationCount:5];

線程池中的線程數(shù),也就是并發(fā)操作數(shù)庇配。默認情況下是-1斩跌,-1表示沒有限制,這樣會同時運行隊列中的全部的操作讨永。

介紹:

Grand Central Dispatch 簡稱(GCD)是蘋果公司開發(fā)的技術滔驶,以優(yōu)化的應用程序支持多核心處理器和其他的對稱多處理系統(tǒng)的系統(tǒng)。這建立在任務并行執(zhí)行的線程池模式的基礎上的卿闹。它首次發(fā)布在Mac OS X 10.6 揭糕,iOS 4及以上也可用萝快。

設計:

GCD的工作原理是:讓程序平行排隊的特定任務,根據(jù)可用的處理資源著角,安排他們在任何可用的處理器核心上執(zhí)行任務揪漩。

一個任務可以是一個函數(shù)(function)或者是一個block。 GCD的底層依然是用線程實現(xiàn)吏口,不過這樣可以讓程序員不用關注實現(xiàn)的細節(jié)奄容。

GCD中的FIFO隊列稱為dispatch queue,它可以保證先進來的任務先得到執(zhí)行
dispatch queue分為下面三種:

Serial

又稱為private dispatch queues产徊,同時只執(zhí)行一個任務昂勒。Serial queue通常用于同步訪問特定的資源或數(shù)據(jù)。當你創(chuàng)建多個Serial queue時舟铜,雖然它們各自是同步執(zhí)行的戈盈,但Serial queue與Serial queue之間是并發(fā)執(zhí)行的。

Concurrent

又稱為global dispatch queue谆刨,可以并發(fā)地執(zhí)行多個任務塘娶,但是執(zhí)行完成的順序是隨機的。

Main dispatch queue

它是全局可用的serial queue痊夭,它是在應用程序主線程上執(zhí)行任務的刁岸。

我們看看dispatch queue如何使用

1、常用的方法dispatch_async

為了避免界面在處理耗時的操作時卡死她我,比如讀取網(wǎng)絡數(shù)據(jù)虹曙,IO,數(shù)據(jù)庫讀寫等,我們會在另外一個線程中處理這些操作鸦难,然后通知主線程更新界面根吁。

用GCD實現(xiàn)這個流程的操作比前面介紹的NSThread NSOperation的方法都要簡單。代碼框架結(jié)構如下:

[cpp] view plaincopy

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗時的操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
});
});

[cpp] view plaincopy

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL url = [NSURL URLWithString:@"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"];
NSData data = [[NSData alloc]initWithContentsOfURL:url];
UIImage *image = [[UIImage alloc]initWithData:data];
if (data != nil) {
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}
});

運行顯示:

是不是代碼比NSThread NSOperation簡潔很多合蔽,而且GCD會自動根據(jù)任務在多核處理器上分配資源击敌,優(yōu)化程序。
系統(tǒng)給每一個應用程序提供了三個concurrent dispatch queues拴事。這三個并發(fā)調(diào)度隊列是全局的沃斤,它們只有優(yōu)先級的不同。因為是全局的刃宵,我們不需要去創(chuàng)建衡瓶。我們只需要通過使用函數(shù)dispath_get_global_queue去得到隊列,如下:

[cpp] view plaincopy

dispatch_queue_t globalQ = 
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

這里也用到了系統(tǒng)默認就有一個串行隊列main_queue

[cpp] view plaincopy

dispatch_queue_t mainQ = dispatch_get_main_queue();

雖然dispatch queue是引用計數(shù)的對象牲证,但是以上兩個都是全局的隊列哮针,不用retain或release。

2、dispatch_group_async的使用

dispatch_group_async可以實現(xiàn)監(jiān)聽一組任務是否完成十厢,完成后得到通知執(zhí)行其他的操作等太。這個方法很有用,比如你執(zhí)行三個下載任務蛮放,當三個任務都下載完成后你才通知界面說完成的了缩抡。下面是一段例子代碼:

[cpp] view plaincopy

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group1");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"group3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"updateUi");
});
dispatch_release(group);
dispatch_group_async是異步的方法,運行后可以看到打印結(jié)果:
2012-09-25 16:04:16.737 gcdTest[43328:11303] group1
2012-09-25 16:04:17.738 gcdTest[43328:12a1b] group2
2012-09-25 16:04:18.738 gcdTest[43328:13003] group3
2012-09-25 16:04:18.739 gcdTest[43328:f803] updateUi

每個一秒打印一個包颁,當?shù)谌齻€任務執(zhí)行后瞻想,upadteUi被打印。

3娩嚼、dispatch_barrier_async的使用

dispatch_barrier_async是在前面的任務執(zhí)行結(jié)束后它才執(zhí)行蘑险,而且它后面的任務等它執(zhí)行完成之后才會執(zhí)行

例子代碼如下:

[cpp] view plaincopy

dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"dispatch_async2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread sleepForTimeInterval:4];

});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
});
打印結(jié)果:
2012-09-25 16:20:33.967 gcdTest[45547:11203] dispatch_async1

2012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_async2

2012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_barrier_async

2012-09-25 16:20:40.970 gcdTest[45547:11303] dispatch_async3

請注意執(zhí)行的時間,可以看到執(zhí)行的順序如上所述岳悟。
4漠其、dispatch_apply

執(zhí)行某個代碼片段N次。

dispatch_apply(5, globalQ, ^(size_t index) {
// 執(zhí)行5次
});
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末竿音,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖说贝,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扯罐,死亡現(xiàn)場離奇詭異,居然都是意外死亡结执,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來萄涯,“玉大人,你說我怎么就攤上這事唆鸡±杂埃” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵争占,是天一觀的道長燃逻。 經(jīng)常有香客問我,道長臂痕,這世上最難降的妖魔是什么伯襟? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮握童,結(jié)果婚禮上姆怪,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好稽揭,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布俺附。 她就那樣靜靜地躺著,像睡著了一般淀衣。 火紅的嫁衣襯著肌膚如雪昙读。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天膨桥,我揣著相機與錄音蛮浑,去河邊找鬼。 笑死只嚣,一個胖子當著我的面吹牛沮稚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播册舞,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼蕴掏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了调鲸?” 一聲冷哼從身側(cè)響起盛杰,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎藐石,沒想到半個月后即供,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡于微,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年逗嫡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片株依。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡驱证,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恋腕,到底是詐尸還是另有隱情抹锄,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布荠藤,位于F島的核電站祈远,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏商源。R本人自食惡果不足惜车份,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望牡彻。 院中可真熱鬧扫沼,春花似錦出爹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至器罐,卻和暖如春梢为,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背轰坊。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工铸董, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肴沫。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓粟害,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颤芬。 傳聞我的和親對象是個殘疾皇子悲幅,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 1、簡介:1.1 iOS有三種多線程編程的技術站蝠,分別是:1.汰具、NSThread2、Cocoa NSOperatio...
    LuckTime閱讀 1,342評論 0 1
  • 一菱魔、前言 上一篇文章iOS多線程淺匯-原理篇中整理了一些有關多線程的基本概念郁副。本篇博文介紹的是iOS中常用的幾個多...
    nuclear閱讀 2,047評論 6 18
  • 在這篇文章中,我將為你整理一下 iOS 開發(fā)中幾種多線程方案豌习,以及其使用方法和注意事項。當然也會給出幾種多線程的案...
    張戰(zhàn)威ican閱讀 603評論 0 0
  • 上一章節(jié):藍月亮21 ----------正文--------------- 第三章畢業(yè)季 2參加社會活動 (10...
    雪漫飛閱讀 547評論 17 11
  • 原諒我一生放縱愛自由莫名喜歡這樣一句話來生長成一棵樹一半在土里安詳一半在風中飛揚拔疚。遙想岳飛當年氣吞萬里如虎肥隆,也難抵...
    c57fb31e8474閱讀 246評論 0 0