国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

多線程開發之一NSThread

2019-11-14 18:27:58
字體:
來源:轉載
供稿:網友

每個 iOS 應用程序都有個專門用來更新顯示 UI 界面、處理用戶的觸摸事件的主線程,因此不能將其他太耗時的操作放在主線程中執行,不然會造成主線程堵塞(出現卡機現象),帶來不好的用戶體驗。

一般的解決方案就是:將那些耗時的操作放到另外一個線程中去執行,多線程編程就是防止主線程堵塞和增加運行效率的最佳方法。

iOS 支持多個層次的多線程編程,層次越高的抽象程度越高,使用也越方便,也是 Apple 最推薦使用的方法。

?下面根據抽象層次從低到高依次列出 iOS 所支持的多線程編程方法:

  1. NSThread :是三種方法里面相對輕量級的,但需要管理線程的生命周期、同步、加鎖問題,這會導致一定的性能開銷

  2. NSOperation:是基于 OC 實現的,NSOperation 以面向對象的方式封裝了需要執行的操作,不必關心線程管理、同步等問題。

    NSOperation 是一個抽象基類,iOS 提供了兩種默認實現:NSInvocationOperation 和 NSBlockOperation,當然也可以自定義 NSOperation

  3. Grand Central Dispatch(簡稱 GCD ,iOS4 才開始支持):提供了一些新特性、運行庫來支持多核并行編程,他的關注點更高:如何在多個 CPU 上提升效率

 

效果如下:

ViewController.h

1 #import <UIKit/UIKit.h>2 3 @interface ViewController : UITableViewController4 @PRoperty (copy, nonatomic) NSArray *arrSampleName;5 6 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName;7 8 @end

ViewController.m

 1 #import "ViewController.h" 2 #import "FirstSampleViewController.h" 3 #import "SecondSampleViewController.h" 4 #import "ThirdSampleViewController.h" 5  6 @interface ViewController () 7 - (void)layoutUI; 8 @end 9 10 @implementation ViewController11 - (void)viewDidLoad {12     [super viewDidLoad];13     14     [self layoutUI];15 }16 17 - (void)didReceiveMemoryWarning {18     [super didReceiveMemoryWarning];19     // Dispose of any resources that can be recreated.20 }21 22 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName {23     if (self = [super initWithStyle:UITableViewStyleGrouped]) {24         self.navigationItem.title = @"多線程開發之一 NSThread";25         self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回首頁" style:UIBarButtonItemStylePlain target:nil action:nil];26         27         _arrSampleName = arrSampleName;28     }29     return self;30 }31 32 - (void)layoutUI {33     34 }35 36 #pragma mark - UITableViewController相關方法重寫37 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {38     return 0.1;39 }40 41 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {42     return 1;43 }44 45 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {46     return [_arrSampleName count];47 }48 49 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {50     static NSString *cellIdentifier = @"cell";51     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];52     if (!cell) {53         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];54     }55     cell.textLabel.text = _arrSampleName[indexPath.row];56     return cell;57 }58 59 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {60     switch (indexPath.row) {61         case 0: {62             FirstSampleViewController *firstSampleVC = [FirstSampleViewController new];63             [self.navigationController pushViewController:firstSampleVC animated:YES];64             break;65         }66         case 1: {67             SecondSampleViewController *secondSampleVC = [SecondSampleViewController new];68             [self.navigationController pushViewController:secondSampleVC animated:YES];69             break;70         }71         case 2: {72             ThirdSampleViewController *thirdSampleVC = [ThirdSampleViewController new];73             [self.navigationController pushViewController:thirdSampleVC animated:YES];74             break;75             76             /*77              類似堆棧的先進后出的原理:78              返回到(上一級)、(任意級)、(根級)導航79             [self.navigationController popViewControllerAnimated:YES];80             [self.navigationController popToViewController:thirdSampleVC animated:YES];81             [self.navigationController popToRootViewControllerAnimated:YES];82              */83         }84         default:85             break;86     }87 }88 89 @end

UIImage+RescaleImage.h

 1 #import <UIKit/UIKit.h> 2  3 @interface UIImage (RescaleImage) 4 /** 5  *  根據寬高大小,獲取對應的縮放圖片 6  * 7  *  @param size 寬高大小 8  * 9  *  @return 對應的縮放圖片10  */11 - (UIImage *)rescaleImageToSize:(CGSize)size;12 13 @end

UIImage+RescaleImage.m

 1 #import "UIImage+RescaleImage.h" 2  3 @implementation UIImage (RescaleImage) 4  5 - (UIImage *)rescaleImageToSize:(CGSize)size { 6     CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height); 7      8     UIGraphicsBeginImageContext(rect.size); 9     [self drawInRect:rect];10     UIImage *imgScale = UIGraphicsGetImageFromCurrentImageContext();11     UIGraphicsEndImageContext();12     13     return imgScale;14 }15 16 @end

KMImageData.h

1 #import <Foundation/Foundation.h>2 3 @interface KMImageData : NSObject4 @property (assign, nonatomic) NSInteger index;5 @property (strong, nonatomic) NSData *data;6 7 - (instancetype)initWithData:(NSData *)data withIndex:(NSInteger)index;8 9 @end

KMImageData.m

 1 #import "KMImageData.h" 2  3 @implementation KMImageData 4  5 - (instancetype)initWithData:(NSData *)data withIndex:(NSInteger)index { 6     if (self = [super init]) { 7         _data = data; 8         _index = index; 9     }10     return self;11 }12 13 @end

FirstSampleViewController.h

1 #import <UIKit/UIKit.h>2 3 @interface FirstSampleViewController : UIViewController4 @property (assign, nonatomic) CGSize rescaleImageSize;5 6 @property (strong, nonatomic) IBOutlet UIImageView *imgV;7 @property (strong, nonatomic) IBOutlet UIButton *btnLoadImage;8 9 @end

FirstSampleViewController.m

 1 #import "FirstSampleViewController.h" 2 #import "UIImage+RescaleImage.h" 3  4 @interface FirstSampleViewController () 5 - (void)layoutUI; 6 - (void)updateImage:(NSData *)imageData; 7 - (void)loadImageFromNetwork; 8 @end 9 10 @implementation FirstSampleViewController11 12 - (void)viewDidLoad {13     [super viewDidLoad];14     15     [self layoutUI];16 }17 18 - (void)didReceiveMemoryWarning {19     [super didReceiveMemoryWarning];20     // Dispose of any resources that can be recreated.21 }22 23 - (void)dealloc {24     _imgV.image = nil;25 }26 27 - (void)layoutUI {28     CGFloat width = [[UIScreen mainScreen] bounds].size.width; //bounds 返回整個屏幕大小;applicationFrame 返回去除狀態欄后的屏幕大小29     CGFloat height = width * 150.0 / 190.0;30     _rescaleImageSize = CGSizeMake(width, height);31     32     //NSString *path = [[NSBundle mainBundle] pathForResource:@"PictureNo@2x" ofType:@"png"];33     //_imgV.image = [UIImage imageWithContentsOfFile:path];34     35     _btnLoadImage.tintColor = [UIColor darkGrayColor];36     _btnLoadImage.layer.masksToBounds = YES;37     _btnLoadImage.layer.cornerRadius = 10.0;38     _btnLoadImage.layer.borderColor = [UIColor grayColor].CGColor;39     _btnLoadImage.layer.borderWidth = 1.0;40 }41 42 - (void)updateImage:(NSData *)imageData {43     UIImage *img = [UIImage imageWithData:imageData];44     _imgV.image = [img rescaleImageToSize:_rescaleImageSize];45 }46 47 - (void)loadImageFromNetwork {48     NSURL *url = [NSURL URLWithString:@"http://images.apple.com/v/macbook/c/overview/images/hero_static_large.jpg"];49     NSData *data = [NSData dataWithContentsOfURL:url];50     51     /*將數據顯示到UI控件,注意只能在主線程中更新UI;52      另外 performSelectorOnMainThread 方法是 NSObject 的分類方法,每個 NSObject 對象都有此方法;53      它調用的 selector 方法是當前調用控件的方法,例如使用 UIImageView 調用的時候 selector 就是 UIImageView 的方法54      withObject:代表調用方法的參數,不過只能傳遞一個參數(如果有多個參數請使用對象進行封裝)55      waitUntilDone:是否線程任務完成執行56      */57     [self performSelectorOnMainThread:@selector(updateImage:)58                            withObject:data59                         waitUntilDone:YES];60 }61 62 - (IBAction)loadImage:(id)sender {63     //方法一:使用線程對象實例方法創建一個線程64     //NSThread *thread = [[NSThread alloc] initWithTarget:self65     //                                           selector:@selector(loadImageFromNetwork)66     //                                             object:nil];67     //[thread start]; //啟動一個線程;注意啟動一個線程并非就一定立即執行,而是處于就緒狀態,當系統調度時才真正執行68     69     //方法二:使用線程類方法創建一個線程70     [NSThread detachNewThreadSelector:@selector(loadImageFromNetwork)71                              toTarget:self72                            withObject:nil];73 }74 75 @end

FirstSampleViewController.xib

 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyaccessControl="none" useAutolayout="YES" useTraitCollections="YES"> 3     <dependencies> 4         <deployment identifier="iOS"/> 5         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/> 6     </dependencies> 7     <objects> 8         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="FirstSampleViewController"> 9             <connections>10                 <outlet property="btnLoadImage" destination="sLs-f1-Gzc" id="kX8-J0-v0V"/>11                 <outlet property="imgV" destination="4Qp-uk-KAb" id="RM3-Ha-glh"/>12                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>13             </connections>14         </placeholder>15         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>16         <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">17             <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>18             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>19             <subviews>20                 <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="PictureNo.png" translatesAutoresizingMaskIntoConstraints="NO" id="4Qp-uk-KAb">21                     <rect key="frame" x="205" y="225" width="190" height="150"/>22                     <constraints>23                         <constraint firstAttribute="height" constant="150" id="S/>24                         <constraint firstAttribute="height" constant="150" id="VwM-i1-atB"/>25                         <constraint firstAttribute="width" constant="190" id="mUh-Bu-tUd"/>26                         <constraint firstAttribute="width" constant="190" id="mdJ-1c-QFa"/>27                         <constraint firstAttribute="width" constant="190" id="sVS-bU-Ty9"/>28                         <constraint firstAttribute="height" constant="150" id="uMG-oN-J56"/>29                         <constraint firstAttribute="height" constant="150" id="vws-Qw-UrB"/>30                     </constraints>31                     <variation key="default">32                         <mask key="constraints">33                             <exclude reference="SIp-Wd-idU"/>34                             <exclude reference="VwM-i1-atB"/>35                             <exclude reference="mUh-Bu-tUd"/>36                             <exclude reference="mdJ-1c-QFa"/>37                             <exclude reference="sVS-bU-Ty9"/>38                             <exclude reference="uMG-oN-J56"/>39                             <exclude reference="vws-Qw-UrB"/>40                         </mask>41                     </variation>42                 </imageView>43                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sLs-f1-Gzc">44                     <rect key="frame" x="230" y="500" width="140" height="50"/>45                     <constraints>46                         <constraint firstAttribute="width" constant="140" id="1jv-9K-mdH"/>47                         <constraint firstAttribute="height" constant="50" id="Q2w-vR-9ac"/>48                     </constraints>49                     <state key="normal" title="加載網絡圖片">50                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>51                     </state>52                     <connections>53                         <action selector="loadImage:" destination="-1" eventType="touchUpInside" id="fdy-Ln-5oS"/>54                     </connections>55                 </button>56             </subviews>57             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>58             <constraints>59                 <constraint firstItem="4Qp-uk-KAb" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="205" id="2a2-mS-WFa"/>60                 <constraint firstItem="sLs-f1-Gzc" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="ES4-wl-RBz"/>61                 <constraint firstItem="4Qp-uk-KAb" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="MUJ-WA-sUf"/>62                 <constraint firstItem="4Qp-uk-KAb" firstAttribute="centerX" secondItem="sLs-f1-Gzc" secondAttribute="centerX" id="Q8a-1k-DzJ"/>63                 <constraint firstAttribute="bottom" secondItem="4Qp-uk-KAb" secondAttribute="bottom" constant="71" id="V0a-9y-Dwa"/>64                 <constraint firstAttribute="bottom" secondItem="sLs-f1-Gzc" secondAttribute="bottom" constant="50" id="VMG-CV-eeq"/>65                 <constraint firstItem="4Qp-uk-KAb" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="-71" id="gqW-Wq-4Zv"/>66                 <constraint firstItem="sLs-f1-Gzc" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="kNf-6d-EJ8"/>67             </constraints>68             <variation key="default">69                 <mask key="constraints">70                     <exclude reference="2a2-mS-WFa"/>71                     <exclude reference="V0a-9y-Dwa"/>72                     <exclude reference="gqW-Wq-4Zv"/>73                     <exclude reference="ES4-wl-RBz"/>74                 </mask>75             </variation>76         </view>77     </objects>78     <resources>79         <image name="PictureNo.png" width="190" height="150"/>80     </resources>81 </document>

SecondSampleViewController.h

SecondSampleViewController.m

  1 #import "SecondSampleViewController.h"  2 #import "KMImageData.h"  3 #import "UIImage+RescaleImage.h"  4   5 #define kRowCount 4  6 #define kColumnCount 3  7 #define kCellSpacing 10.0  8   9 @interface SecondSampleViewController () 10 - (void)layoutUI; 11 - (void)updateImage:(KMImageData *)imageData; 12 -(KMImageData *)requestData:(NSInteger)imageIndex; 13 - (void)loadImageFromNetwork:(NSNumber *)imageIndex; 14 @end 15  16 @implementation SecondSampleViewController 17  18 - (void)viewDidLoad { 19     [super viewDidLoad]; 20      21     [self layoutUI]; 22 } 23  24 - (void)didReceiveMemoryWarning { 25     [super didReceiveMemoryWarning]; 26     // Dispose of any resources that can be recreated. 27 } 28  29 - (void)dealloc { 30     _mArrImageView = nil; 31 } 32  33 - (void)layoutUI { 34     CGFloat width = ([[UIScreen mainScreen] bounds].size.width - ((kColumnCount + 1) * kCellSpacing)) / kColumnCount; 35     _rescaleImageSize = CGSizeMake(width, width); 36      37     CGFloat heightOfStatusAndNav = 20.0 + 44.0; 38     NSString *path = [[NSBundle mainBundle] pathForResource:@"PictureNo@2x" ofType:@"png"]; 39     UIImage *img = [UIImage imageWithContentsOfFile:path]; 40     _mArrImageView = [NSMutableArray arrayWithCapacity:kRowCount * kColumnCount]; 41     //初始化多個圖片視圖 42     for (NSUInteger i=0; i<kRowCount; i++) { 43         for (NSUInteger j=0; j<kColumnCount; j++) { 44             UIImageView *imgV = [[UIImageView alloc] initWithFrame: 45                                  CGRectMake(_rescaleImageSize.width * j + kCellSpacing * (j+1), 46                                             _rescaleImageSize.height * i + kCellSpacing * (i+1) + heightOfStatusAndNav, 47                                             _rescaleImageSize.width, 48                                             _rescaleImageSize.height)]; 49             imgV.image = img; 50             [self.view addSubview:imgV]; 51             [_mArrImageView addObject:imgV]; 52         } 53     } 54      55     _btnLoadImage.tintColor = [UIColor darkGrayColor]; 56     _btnLoadImage.layer.masksToBounds = YES; 57     _btnLoadImage.layer.cornerRadius = 10.0; 58     _btnLoadImage.layer.borderColor = [UIColor grayColor].CGColor; 59     _btnLoadImage.layer.borderWidth = 1.0; 60 } 61  62 - (void)updateImage:(KMImageData *)imageData { 63     UIImage *img = [UIImage imageWithData:imageData.data]; 64     UIImageView *imgVCurrent = _mArrImageView[imageData.index]; 65     imgVCurrent.image = [img rescaleImageToSize:_rescaleImageSize]; 66 } 67  68 -(KMImageData *)requestData:(NSInteger)imageIndex { 69     //對于多線程操作,建議把線程操作放到 @autoreleasepool 中 70     @autoreleasepool { 71         if (imageIndex != kRowCount * kColumnCount - 1) { //雖然設置了最后一個線程的優先級為1.0,但無法保證他是第一個加載的。所以我們這里讓其他線程掛起0.5秒,這樣基本能保證最后一個線程第一個加載,除非網絡非常差的情況 72             [NSThread sleepForTimeInterval:0.5]; 73         } 74          75         NSURL *url = [NSURL URLWithString:@"http://images.apple.com/v/macbook/c/overview/images/hero_static_large.jpg"]; 76         NSData *data = [NSData dataWithContentsOfURL:url]; 77         KMImageData *imageData = [[KMImageData alloc] initWithData:data 78                                                          withIndex:imageIndex]; 79         return imageData; 80     } 81 } 82  83 - (void)loadImageFromNetwork:(NSNumber *)imageIndex { 84     NSLog(@"Current thread:%@",[NSThread currentThread]); 85      86     /*將數據顯示到UI控件,注意只能在主線程中更新UI; 87      另外 performSelectorOnMainThread 方法是 NSObject 的分類方法,每個 NSObject 對象都有此方法; 88      它調用的 selector 方法是當前調用控件的方法,例如使用 UIImageView 調用的時候 selector 就是 UIImageView 的方法 89      withObject:代表調用方法的參數,不過只能傳遞一個參數(如果有多個參數請使用對象進行封裝) 90      waitUntilDone:是否線程任務完成執行 91      */ 92     [self performSelectorOnMainThread:@selector(updateImage:) 93                            withObject:[self requestData:[imageIndex integerValue]] 94                         waitUntilDone:YES]; 95 } 96  97 - (IBAction)loadImage:(id)sender { 98     for (NSUInteger i=0, len=kRowCount * kColumnCount; i<len; i++) { 99         NSThread *thread = [[NSThread alloc] initWithTarget:self100                                                    selector:@selector(loadImageFromNetwork:)101                                                      object:[NSNumber numberWithInteger:i]];102         thread.name = [NSString stringWithFormat:@"Thread %lu", (unsigned long)i];103         thread.threadPriority = i == len-1 ? 1.0 : 0.0; //設置線程優先級;0.0-1.0,值越高優先級越高,這樣可以提高他被優先加載的機率,但是他也未必就第一個加載。因為首先其他線程是先啟動的,其次網絡狀況我們沒辦法修改104         [thread start];105     }106 }107 108 @end

SecondSampleViewController.xib

 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES"> 3     <dependencies> 4         <deployment identifier="iOS"/> 5         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/> 6     </dependencies> 7     <objects> 8         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SecondSampleViewController"> 9             <connections>10                 <outlet property="btnLoadImage" destination="F5h-ZI-gGL" id="I40-e2-bAa"/>11                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>12             </connections>13         </placeholder>14         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>15         <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">16             <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>17             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>18             <subviews>19                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="F5h-ZI-gGL">20                     <rect key="frame" x="230" y="530" width="140" height="50"/>21                     <constraints>22                         <constraint firstAttribute="height" constant="50" id="HWd-Xc-Wk7"/>23                         <constraint firstAttribute="width" constant="140" id="vrH-qE-PNK"/>24                     </constraints>25                     <state key="normal" title="加載網絡圖片">26                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>27                     </state>28                     <connections>29                         <action selector="loadImage:" destination="-1" eventType="touchUpInside" id="Hgw-q8-lHy"/>30                     </connections>31                 </button>32             </subviews>33             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>34             <constraints>35                 <constraint firstAttribute="bottom" secondItem="F5h-ZI-gGL" secondAttribute="bottom" constant="20" id="jPY-fY-9XJ"/>36                 <constraint firstAttribute="centerX" secondItem="F5h-ZI-gGL" secondAttribute="centerX" id="rH1-sV-pST"/>37             </constraints>38         </view>39     </objects>40 </document>

ThirdSampleViewController.h

ThirdSampleViewController.m

  1 #import "ThirdSampleViewController.h"  2 #import "KMImageData.h"  3 #import "UIImage+RescaleImage.h"  4   5 #define kRowCount 4  6 #define kColumnCount 3  7 #define kCellSpacing 10.0  8   9 @interface ThirdSampleViewController () 10 - (void)layoutUI; 11 - (void)updateImage:(KMImageData *)imageData; 12 -(KMImageData *)requestData:(NSInteger)imageIndex; 13 - (void)loadImageFromNetwork:(NSNumber *)imageIndex; 14 @end 15  16 @implementation ThirdSampleViewController 17  18 - (void)viewDidLoad { 19     [super viewDidLoad]; 20      21     [self layoutUI]; 22 } 23  24 - (void)didReceiveMemoryWarning { 25     [super didReceiveMemoryWarning]; 26     // Dispose of any resources that can be recreated. 27 } 28  29 - (void)dealloc { 30     _mArrImageView = nil; 31     _mArrThread = nil; 32 } 33  34 - (void)layoutUI { 35     CGFloat width = ([[UIScreen mainScreen] bounds].size.width - ((kColumnCount + 1) * kCellSpacing)) / kColumnCount; 36     _rescaleImageSize = CGSizeMake(width, width); 37      38     CGFloat heightOfStatusAndNav = 20.0 + 44.0; 39     NSString *path = [[NSBundle mainBundle] pathForResource:@"PictureNo@2x" ofType:@"png"]; 40     UIImage *img = [UIImage imageWithContentsOfFile:path]; 41     _mArrImageView = [NSMutableArray arrayWithCapacity:kRowCount * kColumnCount]; 42     //初始化多個圖片視圖 43     for (NSUInteger i=0; i<kRowCount; i++) { 44         for (NSUInteger j=0; j<kColumnCount; j++) { 45             UIImageView *imgV = [[UIImageView alloc] initWithFrame: 46                                  CGRectMake(_rescaleImageSize.width * j + kCellSpacing * (j+1), 47                                             _rescaleImageSize.height * i + kCellSpacing * (i+1) + heightOfStatusAndNav, 48                                             _rescaleImageSize.width, 49                                             _rescaleImageSize.height)]; 50             imgV.image = img; 51             [self.view addSubview:imgV]; 52             [_mArrImageView addObject:imgV]; 53         } 54     } 55      56     void (^beautifulButton)(UIButton *, UIColor *) = ^(UIButton *btn, UIColor *tintColor) { 57         btn.tintColor = tintColor; 58         btn.layer.masksToBounds = YES; 59         btn.layer.cornerRadius = 10.0; 60         btn.layer.borderColor = [UIColor grayColor].CGColor; 61         btn.layer.borderWidth = 1.0; 62     }; 63      64     beautifulButton(_btnLoadImage, [UIColor darkGrayColor]); 65     beautifulButton(_btnStopLoadImage, [UIColor redColor]); 66 } 67  68 - (void)updateImage:(KMImageData *)imageData { 69     UIImage *img = [UIImage imageWithData:imageData.data]; 70     UIImageView *imgVCurrent = _mArrImageView[imageData.index]; 71     imgVCurrent.image = [img rescaleImageToSize:_rescaleImageSize]; 72 } 73  74 -(KMImageData *)requestData:(NSInteger)imageIndex { 75     //對于多線程操作,建議把線程操作放到 @autoreleasepool 中 76     @autoreleasepool { 77         if (imageIndex != kRowCount * kColumnCount - 1) { //雖然設置了最后一個線程的優先級為1.0,但無法保證他是第一個加載的。所以我們這里讓其他線程掛起0.5秒,這樣基本能保證最后一個線程第一個加載,除非網絡非常差的情況 78             [NSThread sleepForTimeInterval:0.5]; 79         } 80          81         NSURL *url = [NSURL URLWithString:@"http://images.apple.com/v/macbook/c/overview/images/hero_static_large.jpg"]; 82         NSData *data = [NSData dataWithContentsOfURL:url]; 83         KMImageData *imageData = [[KMImageData alloc] initWithData:data 84                                                          withIndex:imageIndex]; 85         return imageData; 86     } 87 } 88  89 - (void)loadImageFromNetwork:(NSNumber *)imageIndex { //子線程中執行 90     //線程狀態:thread.isExecuting(是否執行中)、thread.isFinished(是否已完成)、thread.isCancelled(是否已取消) 91     //thread.isMainThread(是否主線程)、[NSThread isMultiThreaded](是否多線程) 92      93     KMImageData *imageData = [self requestData:[imageIndex integerValue]]; 94      95     NSThread *thread = _mArrThread[[imageIndex integerValue]]; 96     if (thread.isCancelled) { //判斷線程是否已經取消,如是就退出當前線程;這里注意需讓 exit 操作有足夠的時間進行占用資源的釋放,否則有可能出現異常;比如 Demo 中:當點擊「停止加載」按鈕后,再次快速點擊「加載網絡圖片」按鈕 97         NSLog(@"Current thread:%@ will be cancelled.", thread); 98         [NSThread exit]; 99     } else {100 //        //在后臺執行一個方法,本質就是重新創建一個線程來執行方法101 //        [self performSelectorInBackground:@selector(updateImage:) withObject:imageData];102 //        103 //        /*將數據顯示到UI控件,注意只能在主線程中更新UI;104 //         另外 performSelectorOnMainThread 方法是 NSObject 的分類方法,每個 NSObject 對象都有此方法;它調用的 selector 方法是當前調用控件的方法,例如使用 UIImageView 調用的時候 selector 就是 UIImageView 的方法105 //         withObject:代表調用方法的參數,不過只能傳遞一個參數(如果有多個參數請使用對象進行封裝)106 //         waitUntilDone:是否線程任務完成后執行107 //         */108 //        [self performSelectorOnMainThread:@selector(updateImage:)109 //                               withObject:imageData110 //                            waitUntilDone:YES];111         112         @try {113             //在指定的線程上執行一個方法,需要用戶創建一個線程對象實例114             [self performSelector:@selector(updateImage:)115                          onThread:thread116                        withObject:imageData117                     waitUntilDone:YES];118         }119         @catch (NSException *exception) {120             NSLog(@"Exception: %@", [exception description]);121         }122     }123 }124 125 - (IBAction)loadImage:(id)sender {126     NSUInteger len = kRowCount * kColumnCount;127     _mArrThread = [NSMutableArray arrayWithCapacity:len];128     129     //循環創建多個線程130     for (NSUInteger i=0; i<len; i++) {131         NSThread *thread = [[NSThread alloc] initWithTarget:self132                                                    selector:@selector(loadImageFromNetwork:)133                                                      object:[NSNumber numberWithInteger:i]];134         thread.name = [NSString stringWithFormat:@"Thread %lu", (unsigned long)i];135         thread.threadPriority = i == len-1 ? 1.0 : 0.0; //設置線程優先級;0.0-1.0,值越高優先級越高,這樣可以提高他被優先加載的機率,但是他也未必就第一個加載。因為首先其他線程是先啟動的,其次網絡狀況我們沒辦法修改136         [_mArrThread addObject:thread];137     }138     139     //循環啟動線程140     for (NSUInteger i=0; i<len; i++) {141         NSThread *thread = _mArrThread[i];142         [thread start];143     }144 }145 146 - (IBAction)stopLoadImage:(id)sender { //主線程中執行147     for (NSUInteger i=0, len=kRowCount * kColumnCount; i<len; i++) {148         NSThread *thread = _mArrThread[i];149         if (!thread.isFinished) { //判斷線程是否完成,如果沒有完成則設置為取消狀態;取消狀態僅僅是改變了線程狀態而言,并不能終止線程150             [thread cancel];151         }152     }153 }154 155 @end

ThirdSampleViewController.xib

 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES"> 3     <dependencies> 4         <deployment identifier="iOS"/> 5         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/> 6     </dependencies> 7     <objects> 8         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ThirdSampleViewController"> 9             <connections>10                 <outlet property="btnLoadImage" destination="F5h-ZI-gGL" id="I40-e2-bAa"/>11                 <outlet property="btnStopLoadImage" destination="gnu-KE-bGq" id="tOA-t9-OA9"/>12                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>13             </connections>14         </placeholder>15         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>16         <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">17             <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>18             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>19             <subviews>20                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="F5h-ZI-gGL">21                     <rect key="frame" x="20" y="530" width="130" height="50"/>22                     <constraints>23                         <constraint firstAttribute="height" constant="50" id="HWd-Xc-Wk7"/>24                         <constraint firstAttribute="width" constant="130" id="vrH-qE-PNK"/>25                     </constraints>26                     <state key="normal" title="加載網絡圖片">27                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>28                     </state>29                     <connections>30                         <action selector="loadImage:" destination="-1" eventType="touchUpInside" id="Hgw-q8-lHy"/>31                     </connections>32                 </button>33                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gnu-KE-bGq">34                     <rect key="frame" x="450" y="530" width="130" height="50"/>35                     <constraints>36                         <constraint firstAttribute="height" constant="50" id="1R7-22-hMk"/>37                         <constraint firstAttribute="width" constant="130" id="64l-yF-IFO"/>38                     </constraints>39                     <state key="normal" title="停止加載">40                         <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>41                     </state>42                     <connections>43                         <action selector="loadImage:" destination="-1" eventType="touchUpInside" id="PyX-RW-cbL"/>44                         <action selector="stopLoadImage:" destination="-1" eventType="touchUpInside" id="1Xa-Ek-D4B"/>45                     </connections>46                 </button>47             </subviews>48             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>49             <constraints>50                 <constraint firstItem="F5h-ZI-gGL" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="20" id="Glo-vW-SXd"/>51                 <constraint firstAttribute="trailing" secondItem="gnu-KE-bGq" secondAttribute="trailing" constant="20" id="IdF-1v-bg2"/>52                 <constraint firstAttribute="bottom" secondItem="gnu-KE-bGq" secondAttribute="bottom" constant="20" id="cyx-dg-K8M"/>53                 <constraint firstAttribute="bottom" secondItem="F5h-ZI-gGL" secondAttribute="bottom" constant="20" id="jPY-fY-9XJ"/>54                 <constraint firstAttribute="centerX" secondItem="F5h-ZI-gGL" secondAttribute="centerX" id="rH1-sV-pST"/>55             </constraints>56             <variation key="default">57                 <mask key="constraints">58                     <exclude reference="rH1-sV-pST"/>59                 </mask>60             </variation>61         </view>62     </objects>63 </document>

AppDelegate.h

AppDelegate.m

輸出結果:

 1 2015-08-24 22:18:38.945 NSThreadDemo[5361:204621]  INFO: Reveal Server started (Protocol Version 18). 2 2015-08-24 22:18:57.863 NSThreadDemo[5361:204847] Current thread:<NSThread: 0x7f9f60cd1f80>{number = 5, name = Thread 0} 3 2015-08-24 22:18:57.863 NSThreadDemo[5361:204848] Current thread:<NSThread: 0x7f9f60c74800>{number = 6, name = Thread 1} 4 2015-08-24 22:18:57.863 NSThreadDemo[5361:204849] Current thread:<NSThread: 0x7f9f60cb8f30>{number = 7, name = Thread 2} 5 2015-08-24 22:18:57.863 NSThreadDemo[5361:204850] Current thread:<NSThread: 0x7f9f60cb8500>{number = 8, name = Thread 3} 6 2015-08-24 22:18:57.864 NSThreadDemo[5361:204851] Current thread:<NSThread: 0x7f9f60cd0c60>{number = 9, name = Thread 4} 7 2015-08-24 22:18:57.865 NSThreadDemo[5361:204857] Current thread:<NSThread: 0x7f9f60dee540>{number = 11, name = Thread 6} 8 2015-08-24 22:18:57.864 NSThreadDemo[5361:204856] Current thread:<NSThread: 0x7f9f60cd2150>{number = 10, name = Thread 5} 9 2015-08-24 22:18:57.866 NSThreadDemo[5361:204859] Current thread:<NSThread: 0x7f9f60daf730>{number = 13, name = Thread 8}10 2015-08-24 22:18:57.866 NSThreadDemo[5361:204860] Current thread:<NSThread: 0x7f9f60db8530>{number = 14, name = Thread 9}11 2015-08-24 22:18:57.866 NSThreadDemo[5361:204862] Current thread:<NSThread: 0x7f9f60f3f7e0>{number = 16, name = Thread 11}12 2015-08-24 22:18:57.866 NSThreadDemo[5361:204858] Current thread:<NSThread: 0x7f9f60db2390>{number = 12, name = Thread 7}13 2015-08-24 22:18:57.867 NSThreadDemo[5361:204861] Current thread:<NSThread: 0x7f9f60f231c0>{number = 15, name = Thread 10}14 15 2015-08-24 22:19:07.073 NSThreadDemo[5361:204952] Current thread:<NSThread: 0x7f9f63010930>{number = 39, name = Thread 10} will be cancelled.16 2015-08-24 22:19:07.691 NSThreadDemo[5361:204951] Current thread:<NSThread: 0x7f9f60df0210>{number = 38, name = Thread 9} will be cancelled.17 2015-08-24 22:19:07.697 NSThreadDemo[5361:204957] Current thread:<NSThread: 0x7f9f60db8ee0>{number = 29, name = Thread 0} will be cancelled.18 2015-08-24 22:19:07.729 NSThreadDemo[5361:204958] Current thread:<NSThread: 0x7f9f60db2390>{number = 30, name = Thread 1} will be cancelled.19 2015-08-24 22:19:07.857 NSThreadDemo[5361:204949] Current thread:<NSThread: 0x7f9f63011190>{number = 36, name = Thread 7} will be cancelled.20 2015-08-24 22:19:08.025 NSThreadDemo[5361:204960] Current thread:<NSThread: 0x7f9f6300c2d0>{number = 32, name = Thread 3} will be cancelled.21 2015-08-24 22:19:08.047 NSThreadDemo[5361:204959] Current thread:<NSThread: 0x7f9f60dd4200>{number = 31, name = Thread 2} will be cancelled.22 2015-08-24 22:19:08.191 NSThreadDemo[5361:204942] Current thread:<NSThread: 0x7f9f60db8ee0>{number = 29, name = Thread 0} will be cancelled.23 2015-08-24 22:19:08.250 NSThreadDemo[5361:204965] Current thread:<NSThread: 0x7f9f630110b0>{number = 37, name = Thread 8} will be cancelled.24 2015-08-24 22:19:08.416 NSThreadDemo[5361:204962] Current thread:<NSThread: 0x7f9f60df7bc0>{number = 34, name = Thread 5} will be cancelled.25 2015-08-24 22:19:08.464 NSThreadDemo[5361:204963] Current thread:<NSThread: 0x7f9f60dc5ca0>{number = 35, name = Thread 6} will be cancelled.26 2015-08-24 22:19:08.495 NSThreadDemo[5361:204964] Current thread:<NSThread: 0x7f9f63011190>{number = 36, name = Thread 7} will be cancelled.27 2015-08-24 22:19:08.661 NSThreadDemo[5361:204966] Current thread:<NSThread: 0x7f9f60df0210>{number = 38, name = Thread 9} will be cancelled.28 2015-08-24 22:19:10.033 NSThreadDemo[5361:204961] Current thread:<NSThread: 0x7f9f60da3330>{number = 33, name = Thread 4} will be cancelled.29 2015-08-24 22:19:10.056 NSThreadDemo[5361:204967] Current thread:<NSThread: 0x7f9f63010930>{number = 39, name = Thread 10} will be cancelled.

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 会昌县| 靖江市| 清苑县| 吕梁市| 宝清县| 思茅市| 洛宁县| 手机| 洛南县| 如皋市| 色达县| 洪洞县| 田东县| 桃园市| 容城县| 金沙县| 顺平县| 洛川县| 平谷区| 东乌珠穆沁旗| 贵港市| 原阳县| 绵竹市| 行唐县| 额济纳旗| 和林格尔县| 民勤县| 虎林市| 无锡市| 大余县| 龙泉市| 嫩江县| 五指山市| 自贡市| 梁山县| 河北省| 东乡县| 湛江市| 获嘉县| 平塘县| 聂拉木县|