效果如下:

ViewController.h

 #import <UIKit/UIKit.h>

 @interface ViewController : UITableViewController
@property (copy, nonatomic) NSArray *arrSampleName; - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName; @end 

ViewController.m

 #import "ViewController.h"
#import "FirstSampleViewController.h"
#import "SecondSampleViewController.h" @interface ViewController ()
- (void)layoutUI;
@end @implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad]; [self layoutUI];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName {
if (self = [super initWithStyle:UITableViewStyleGrouped]) {
self.navigationItem.title = @"多线程开发之二 NSOperation";
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回首页" style:UIBarButtonItemStylePlain target:nil action:nil]; _arrSampleName = arrSampleName;
}
return self;
} - (void)layoutUI {
} #pragma mark - UITableViewController相关方法重写
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 0.1;
} - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return ;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_arrSampleName count];
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = _arrSampleName[indexPath.row];
return cell;
} - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.row) {
case : {
FirstSampleViewController *firstSampleVC = [FirstSampleViewController new];
[self.navigationController pushViewController:firstSampleVC animated:YES];
break;
}
case : {
SecondSampleViewController *secondSampleVC = [SecondSampleViewController new];
[self.navigationController pushViewController:secondSampleVC animated:YES];
break;
}
default:
break;
}
} @end 

UIImage+RescaleImage.h

 #import <UIKit/UIKit.h>

 @interface UIImage (RescaleImage)
/**
* 根据宽高大小,获取对应的缩放图片
*
* @param size 宽高大小
*
* @return 对应的缩放图片
*/
- (UIImage *)rescaleImageToSize:(CGSize)size; @end 

UIImage+RescaleImage.m

 #import "UIImage+RescaleImage.h"

 @implementation UIImage (RescaleImage)

 - (UIImage *)rescaleImageToSize:(CGSize)size {
CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height); UIGraphicsBeginImageContext(rect.size);
[self drawInRect:rect];
UIImage *imgScale = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); return imgScale;
} @end 

Common.h

 #import <Foundation/Foundation.h>

 @interface Common : NSObject
+ (NSURL *)randomImageURL; @end 

Common.m

 #import "Common.h"

 @implementation Common

 + (NSURL *)randomImageURL {
NSUInteger randomVal = (arc4random() % ) + ; //1-20的随机数
NSString *randomValStr = [NSString stringWithFormat:@"%lu", (unsigned long)randomVal];
if (randomVal < ) {
randomValStr = [@"" stringByAppendingString:randomValStr];
} NSString *imageURLStr = [NSString stringWithFormat:@"http://images.apple.com/v/watch/e/apple-watch/images/collection_%@_large.jpg", randomValStr];
return [NSURL URLWithString:imageURLStr];
} @end 

FirstSampleViewController.h

 #import <UIKit/UIKit.h>

 @interface FirstSampleViewController : UIViewController
@property (assign, nonatomic) CGSize rescaleImageSize; @property (strong, nonatomic) IBOutlet UIImageView *imgV;
@property (strong, nonatomic) IBOutlet UIButton *btnLoadImage; @end 

FirstSampleViewController.m

 #import "FirstSampleViewController.h"
#import "UIImage+RescaleImage.h"
#import "Common.h" @interface FirstSampleViewController ()
- (void)layoutUI;
- (void)updateImage:(NSData *)imageData;
- (void)loadImageFromNetwork;
@end @implementation FirstSampleViewController - (void)viewDidLoad {
[super viewDidLoad]; [self layoutUI];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)dealloc {
_imgV.image = nil;
} - (void)layoutUI {
CGFloat width = [[UIScreen mainScreen] bounds].size.width; //bounds 返回整个屏幕大小;applicationFrame 返回去除状态栏后的屏幕大小
CGFloat height = width * 438.0 / 366.0;
const CGFloat percentVal = 3.0 / 4.0; //以屏幕宽度的3/4比例显示
_rescaleImageSize = CGSizeMake(width * percentVal, height * percentVal); //NSString *path = [[NSBundle mainBundle] pathForResource:@"PictureNo@2x" ofType:@"png"];
//_imgV.image = [UIImage imageWithContentsOfFile:path]; _btnLoadImage.tintColor = [UIColor darkGrayColor];
_btnLoadImage.layer.masksToBounds = YES;
_btnLoadImage.layer.cornerRadius = 10.0;
_btnLoadImage.layer.borderColor = [UIColor grayColor].CGColor;
_btnLoadImage.layer.borderWidth = 1.0;
} - (void)updateImage:(NSData *)imageData {
UIImage *img = [UIImage imageWithData:imageData];
_imgV.image = [img rescaleImageToSize:_rescaleImageSize];
} - (void)loadImageFromNetwork {
NSURL *url = [Common randomImageURL];
NSData *data = [NSData dataWithContentsOfURL:url]; //mainQueue 是 UI 主线程,调用主线程队列的方法进行操作
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self updateImage:data];
}];
} - (IBAction)loadImage:(id)sender {
//方法一:使用 NSInvocationOperation
// NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc]
// initWithTarget:self
// selector:@selector(loadImageFromNetwork)
// object:nil];
// NSOperationQueue *operationQueue = [NSOperationQueue new]; //操作队列
// [operationQueue addOperation:invocationOperation]; //方法二:使用 NSBlockOperation
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
[self loadImageFromNetwork];
}];
[blockOperation addExecutionBlock:^{ //还可以为 blockOperation 添加代码块;多个代码块会被分到多个线程去执行,存在两个代码块被分配到同一个线程执行的情况
NSLog(@"代码块");
}];
[blockOperation addExecutionBlock:[blockOperation executionBlocks][]]; //这里可以调用他的 executionBlocks 获取到添加的代码块数组;上面打印的内容「代码块」会被执行两次 [blockOperation setCompletionBlock:^{
NSLog(@"所有代码块操作执行完毕后(无论已取消还是已完成),做一些事情,只执行一次");
}]; //[blockOperation start]; //使用 start 方法,则此操作在主线程中执行;一般不这样操作,而是添加到操作队列中
NSOperationQueue *operationQueue = [NSOperationQueue new]; //操作队列
[operationQueue addOperation:blockOperation]; //添加到操作队列,这时队列会开启一个线程去执行此操作;一个线程可以执行多个操作 //方法三:直接使用 NSOperationQueue
// NSOperationQueue *operationQueue = [NSOperationQueue new]; //操作队列
// [operationQueue addOperationWithBlock:^{
// [self loadImageFromNetwork];
// }];
} @end 

FirstSampleViewController.xib

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="FirstSampleViewController">
<connections>
<outlet property="btnLoadImage" destination="sLs-f1-Gzc" id="kX8-J0-v0V"/>
<outlet property="imgV" destination="4Qp-uk-KAb" id="RM3-Ha-glh"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="PictureNo.png" translatesAutoresizingMaskIntoConstraints="NO" id="4Qp-uk-KAb">
<rect key="frame" x="205" y="225" width="190" height="150"/>
<constraints>
<constraint firstAttribute="height" constant="150" id="SIp-Wd-idU"/>
<constraint firstAttribute="height" constant="150" id="VwM-i1-atB"/>
<constraint firstAttribute="width" constant="190" id="mUh-Bu-tUd"/>
<constraint firstAttribute="width" constant="190" id="mdJ-1c-QFa"/>
<constraint firstAttribute="width" constant="190" id="sVS-bU-Ty9"/>
<constraint firstAttribute="height" constant="150" id="uMG-oN-J56"/>
<constraint firstAttribute="height" constant="150" id="vws-Qw-UrB"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="SIp-Wd-idU"/>
<exclude reference="VwM-i1-atB"/>
<exclude reference="mUh-Bu-tUd"/>
<exclude reference="mdJ-1c-QFa"/>
<exclude reference="sVS-bU-Ty9"/>
<exclude reference="uMG-oN-J56"/>
<exclude reference="vws-Qw-UrB"/>
</mask>
</variation>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sLs-f1-Gzc">
<rect key="frame" x="230" y="500" width="140" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="140" id="1jv-9K-mdH"/>
<constraint firstAttribute="height" constant="50" id="Q2w-vR-9ac"/>
</constraints>
<state key="normal" title="加载网络图片">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="loadImage:" destination="-1" eventType="touchUpInside" id="fdy-Ln-5oS"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="4Qp-uk-KAb" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="205" id="2a2-mS-WFa"/>
<constraint firstItem="sLs-f1-Gzc" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="ES4-wl-RBz"/>
<constraint firstItem="4Qp-uk-KAb" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="MUJ-WA-sUf"/>
<constraint firstItem="4Qp-uk-KAb" firstAttribute="centerX" secondItem="sLs-f1-Gzc" secondAttribute="centerX" id="Q8a-1k-DzJ"/>
<constraint firstAttribute="bottom" secondItem="4Qp-uk-KAb" secondAttribute="bottom" constant="71" id="V0a-9y-Dwa"/>
<constraint firstAttribute="bottom" secondItem="sLs-f1-Gzc" secondAttribute="bottom" constant="50" id="VMG-CV-eeq"/>
<constraint firstItem="4Qp-uk-KAb" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="-71" id="gqW-Wq-4Zv"/>
<constraint firstItem="sLs-f1-Gzc" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="kNf-6d-EJ8"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="2a2-mS-WFa"/>
<exclude reference="V0a-9y-Dwa"/>
<exclude reference="gqW-Wq-4Zv"/>
<exclude reference="ES4-wl-RBz"/>
</mask>
</variation>
</view>
</objects>
<resources>
<image name="PictureNo.png" width="190" height="150"/>
</resources>
</document> 

SecondSampleViewController.h

 #import <UIKit/UIKit.h>

 @interface SecondSampleViewController : UIViewController
@property (assign, nonatomic) CGSize rescaleImageSize;
@property (strong, nonatomic) NSMutableArray *mArrImageView; @property (strong, nonatomic) IBOutlet UIButton *btnLoadImage; @end 

SecondSampleViewController.m

 #import "SecondSampleViewController.h"
#import "UIImage+RescaleImage.h"
#import "Common.h" #define kRowCount 4
#define kColumnCount 3
#define kCellSpacing 10.0 @interface SecondSampleViewController ()
- (void)layoutUI;
- (void)updateImage:(NSData *)imageData withImageIndex:(NSInteger)imageIndex;
-(NSData *)requestData:(NSInteger)imageIndex;
- (void)loadImageFromNetwork:(NSInteger)imageIndex;
@end @implementation SecondSampleViewController - (void)viewDidLoad {
[super viewDidLoad]; [self layoutUI];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)dealloc {
_mArrImageView = nil;
} - (void)layoutUI {
CGFloat width = ([[UIScreen mainScreen] bounds].size.width - ((kColumnCount + ) * kCellSpacing)) / kColumnCount;
_rescaleImageSize = CGSizeMake(width, width); CGFloat heightOfStatusAndNav = 20.0 + 44.0;
NSString *path = [[NSBundle mainBundle] pathForResource:@"PictureNo@2x" ofType:@"png"];
UIImage *img = [UIImage imageWithContentsOfFile:path];
_mArrImageView = [NSMutableArray arrayWithCapacity:kRowCount * kColumnCount];
//初始化多个图片视图
for (NSUInteger i=; i<kRowCount; i++) {
for (NSUInteger j=; j<kColumnCount; j++) {
UIImageView *imgV = [[UIImageView alloc] initWithFrame:
CGRectMake(_rescaleImageSize.width * j + kCellSpacing * (j+),
_rescaleImageSize.height * i + kCellSpacing * (i+) + heightOfStatusAndNav,
_rescaleImageSize.width,
_rescaleImageSize.height)];
imgV.image = img;
[self.view addSubview:imgV];
[_mArrImageView addObject:imgV];
}
} _btnLoadImage.tintColor = [UIColor darkGrayColor];
_btnLoadImage.layer.masksToBounds = YES;
_btnLoadImage.layer.cornerRadius = 10.0;
_btnLoadImage.layer.borderColor = [UIColor grayColor].CGColor;
_btnLoadImage.layer.borderWidth = 1.0;
} - (void)updateImage:(NSData *)imageData withImageIndex:(NSInteger)imageIndex {
UIImage *img = [UIImage imageWithData:imageData];
UIImageView *imgVCurrent = _mArrImageView[imageIndex];
imgVCurrent.image = [img rescaleImageToSize:_rescaleImageSize];
} -(NSData *)requestData:(NSInteger)imageIndex {
//对于多线程操作,建议把线程操作放到 @autoreleasepool 中
@autoreleasepool {
NSURL *url = [Common randomImageURL];
NSData *data = [NSData dataWithContentsOfURL:url];
return data;
}
} - (void)loadImageFromNetwork:(NSInteger)imageIndex {
/*
对比之前 NSThread 加载图片,你会发现核心代码简化了不少,有两点值得提的:
(1)使用 NSBlockOperation 方法,所有的操作不必单独定义方法,同时解决了只能传递一个参数的问题。类似的操作,例如:调用主线程队列的 addOperationWithBlock: 方法进行 UI 更新,不用再定义一个参数实体类来进行参数传递(之前必须定义一个 KMImageData 解决只能传递一个参数的问题)。
(2)使用 NSOperation 进行多线程开发可以设置最大并发操作数,有效的对操作进行控制(如 Demo 的代码设置最大并发操作数为5,则图片最多是五个一次加载的)。
*/
NSLog(@"Current thread:%@", [NSThread currentThread]); //mainQueue 是 UI 主线程,调用主线程队列的方法进行操作
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self updateImage:[self requestData:imageIndex] withImageIndex:imageIndex];
}];
} - (IBAction)loadImage:(id)sender {
NSOperationQueue *operationQueue = [NSOperationQueue new];
operationQueue.maxConcurrentOperationCount = ; //设置最大并发操作数 NSUInteger len = kRowCount * kColumnCount;
NSBlockOperation *lastBlockOperation = [NSBlockOperation blockOperationWithBlock:^{
[self loadImageFromNetwork:len - ];
}]; for (NSUInteger i=; i<len - ; i++) {
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
[self loadImageFromNetwork:i];
}]; //实现控制「操作执行顺序」,例如:控制最后一个操作第一个执行,这里设置操作的依赖关系为:最后一张图片加载操作完成后才执行
//PS:注意请勿进行循环依赖,否则循环依赖相关的操作是不会被执行的
//这里添加依赖关系;其相对应的移除方法:- (void)removeDependency:(NSOperation *)op;
[blockOperation addDependency:lastBlockOperation]; //另外添加操作对象实例数组的方法:- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait;
[operationQueue addOperation:blockOperation];
} [operationQueue addOperation:lastBlockOperation]; /*
lastBlockOperation.queuePriority = NSOperationQueuePriorityVeryHigh; //在某个操作队列中的队列优先级;这样可以提高他被优先加载的机率,但是他也未必就第一个加载;所以要实现控制「操作执行顺序」,就得用设置操作的依赖关系的方式 typedef enum : NSInteger {
NSOperationQueuePriorityVeryLow = -8,
NSOperationQueuePriorityLow = -4,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
} NSOperationQueuePriority;
*/
} @end 

SecondSampleViewController.xib

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SecondSampleViewController">
<connections>
<outlet property="btnLoadImage" destination="F5h-ZI-gGL" id="I40-e2-bAa"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="F5h-ZI-gGL">
<rect key="frame" x="230" y="530" width="140" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="HWd-Xc-Wk7"/>
<constraint firstAttribute="width" constant="140" id="vrH-qE-PNK"/>
</constraints>
<state key="normal" title="加载网络图片">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="loadImage:" destination="-1" eventType="touchUpInside" id="Hgw-q8-lHy"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="F5h-ZI-gGL" secondAttribute="bottom" constant="20" id="jPY-fY-9XJ"/>
<constraint firstAttribute="centerX" secondItem="F5h-ZI-gGL" secondAttribute="centerX" id="rH1-sV-pST"/>
</constraints>
</view>
</objects>
</document> 

AppDelegate.h

 #import <UIKit/UIKit.h>

 @interface AppDelegate : UIResponder <UIApplicationDelegate>

 @property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UINavigationController *navigationController; @end 

AppDelegate.m

 #import "AppDelegate.h"
#import "ViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController *viewController = [[ViewController alloc] initWithSampleNameArray:@[@"请求单张网络图片(解决线程阻塞)", @"请求多张网络图片(多个线程并发)"]];
_navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
_window.rootViewController = _navigationController;
//[_window addSubview:_navigationController.view]; //当_window.rootViewController关联时,这一句可有可无
[_window makeKeyAndVisible];
return YES;
} - (void)applicationWillResignActive:(UIApplication *)application {
} - (void)applicationDidEnterBackground:(UIApplication *)application {
} - (void)applicationWillEnterForeground:(UIApplication *)application {
} - (void)applicationDidBecomeActive:(UIApplication *)application {
} - (void)applicationWillTerminate:(UIApplication *)application {
} @end 

输出结果:

 -- ::36.878 NSOperationDemo[:] 代码块
-- ::36.878 NSOperationDemo[:] 代码块
-- ::37.366 NSOperationDemo[:] 所有代码块操作执行完毕后(无论已取消还是已完成),做一些事情,只执行一次 -- ::42.505 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1bd335b0>{number = , name = (null)}
-- ::42.506 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1be0ad90>{number = , name = (null)}
-- ::42.507 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1e047390>{number = , name = (null)}
-- ::42.507 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1e047390>{number = , name = (null)}
-- ::42.507 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1be0ad90>{number = , name = (null)}
-- ::42.507 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1be07c70>{number = , name = (null)}
-- ::42.508 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1be0ad90>{number = , name = (null)}
-- ::42.508 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1be07c70>{number = , name = (null)}
-- ::42.508 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1be0ad90>{number = , name = (null)}
-- ::42.508 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1e047390>{number = , name = (null)}
-- ::42.508 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1e0335f0>{number = , name = (null)}
-- ::42.508 NSOperationDemo[:] Current thread:<NSThread: 0x7fbd1be0ad90>{number = , name = (null)}

多线程开发之二 NSOperation的更多相关文章

  1. iOS之多线程开发NSThread、NSOperation、GCD

    原文出处: 容芳志的博客   欢迎分享原创到伯乐头条 简介iOS有三种多线程编程的技术,分别是:(一)NSThread(二)Cocoa NSOperation(三)GCD(全称:Grand Centr ...

  2. ios 多线程开发(二)线程管理

    线程管理 iOS和OS X中每一个进程(或程序)由一个或多个线程组成.程序由一个运行main方法的线程开始,中间可以产生其他线程来执行一些指定的功能. 当程序产生一个新线程后,这个线程在程序进程空间内 ...

  3. iOS多线程开发--NSThread NSOperation GCD

    多线程 当用户播放音频.下载资源.进行图像处理时往往希望做这些事情的时候其他操作不会被中 断或者希望这些操作过程中更加顺畅.在单线程中一个线程只能做一件事情,一件事情处理不完另一件事就不能开始,这样势 ...

  4. iOS开发之多线程(NSThread、NSOperation、GCD)

    整理一些多线程相关的知识. 并行 & 并发 1.并行:并行是相对于多核而言的,几个任务同时执行.2.并发:并发是相对于单核而言的,几个任务之间快速切换运行,看起来像是"同时" ...

  5. 多线程开发之三 GCD

    NSThread.NSOperation.GCD 总结: 无论使用哪种方法进行多线程开发,每个线程启动后并不一定立即执行相应的操作,具体什么时候由系统调度(CPU 空闲时就会执行) 更新 UI 应该在 ...

  6. 多线程开发之一 NSThread

    每个 iOS 应用程序都有个专门用来更新显示 UI 界面.处理用户的触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来不好的用户体验. 一般的解决 ...

  7. .NET基础拾遗(5)多线程开发基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  8. Java多线程开发系列之番外篇:事件派发线程---EventDispatchThread

    事件派发线程是java Swing开发中重要的知识点,在安卓app开发中,也是非常重要的一点.今天我们在多线程开发中,穿插进来这个线程.分别从线程的来由.原理和使用方法三个方面来学习事件派发线程. 一 ...

  9. Java多线程开发系列之一:走进多线程

    对编程语言的基础知识:分支.选择.循环.面向对象等基本概念理解后,我们需要对java高级编程有一定的学习,这里不可避免的要接触到多线程开发. 由于多线程开发整体的系统比较大,我会写一个系列的文章总结介 ...

随机推荐

  1. 学JAVA二十一天,自定义数组

    今天就说一下自定义数组,至于要怎么用,我也不知道,反正逼格挺高的. 闲话不多说,开始: 首先,自定义数组首先要创建一个类,用来做自定义数组的类型. public class User{ private ...

  2. HTML:DOM 对象

    ylbtech-HTML:DOM 对象 1. Document 对象返回顶部 1-1. Document 对象 每个载入浏览器的 HTML 文档都会成为 Document 对象. Document 对 ...

  3. Go语言之高级篇beego框架之请求数据处理

    1.Controller中数据参数处理 获取参数:我们经常需要获取用户传递的数据,包括 Get.POST 等方式的请求,beego 里面会自动解析这些数据,你可以通过如下方式获取数据: GetStri ...

  4. jquery异步ajax与服务器通信过程中如何通过then方法链式传递多层数据

    我们在有些地方可能需要对服务器返回的参数做多步处理,或者很多复杂的操作必须等到服务器返回结果之后才会执行,那么我们可以用链式调用的then方法让这里做到更加易于扩展,也更加容易分离出各个功能模块.基本 ...

  5. H5使用Swiper过程中遇到的滑动冲突

    一.问题 (1)PC端可以鼠标可以拖动中间的轮子让页面上下滑动,点击左键按着也是拖不动 (2)手机端浏览H5手指不能滑动页面,导致很多页面下面的文字看不到 二.解决问题 1.下面分先说css的问题,主 ...

  6. 用户人品预测大赛--就是gan队--竞赛分享

     用户人品预测大赛--就是gan队--竞赛分享  DataCastle运营 发表于 2016-3-24 14:14:05      1194  1  0 答辩PPT

  7. [Spring Unit Testing] Spring Unit Testing with a Java Context

    For example, we want to test against a implemataion: package com.example.in28minutes.basic; import o ...

  8. 浅谈压缩感知(十七):测量矩阵之有限等距常数RIC的计算

    有限等距常数(RestrictedIsometry Constant, RIC)是与有限等距性质(Restricted IsometryProperty, RIP)紧密结合在一起的一个参数. 一.RI ...

  9. Java 对字符串数据进行MD5/SHA1哈希散列运算

    Java对字符串数据进行MD5/SHA1哈希散列运算 [java] view plain copy package cn.aibo.test; import java.security.Message ...

  10. Mac下用zsh

    最近好多实验要跑,有时候Finder切换来切换去,感觉还不如用terminal. Mac默认的shell是bash.所以说我其实今天才弄明白shell和terminal之间的关系.在人和计算机内核之间 ...