成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iOS中多線程原理與runloop介紹

移動開發(fā) iOS
iPhone中的線程應用并不是無節(jié)制的,官方給出的資料顯示iPhone OS下的主線程的堆棧大小是1M,第二個線程開始都是512KB。并且該值不能通過編譯器開關或線程API函數(shù)來更改。只有主線程有直接修改UI的能力。

 

一.線程概述

有些程序是一條直線,起點到終點;有些程序是一個圓,不斷循環(huán),直到將它切斷。直線的如簡單的Hello World,運行打印完,它的生命周期便結(jié)束了,像曇花一現(xiàn)那樣;圓如操作系統(tǒng),一直運行直到你關機。 
一個運行著的程序就是一個進程或者叫做一個任務,一個進程至少包含一個線程,線程就是程序的執(zhí)行流。Mac和iOS中的程序啟動,創(chuàng)建好一個進程的同時, 一個線程便開始運行,這個線程叫主線程。主線程在程序中的地位和其他線程不同,它是其他線程最終的父線程,且所有界面的顯示操作即AppKit或 UIKit的操作必須在主線程進行。 
系統(tǒng)中的每一個進程都有自己獨立的虛擬內(nèi)存空間,而同一個進程中的多個線程則共用進程的內(nèi)存空間。每創(chuàng)建一個新的線程,都需要一些內(nèi)存(如每個線程有自己的Stack空間)和消耗一定的CPU時間。另外當多個線程對同一個資源出現(xiàn)爭奪的時候需要注意線程安全問題。

 

二.創(chuàng)建線程

創(chuàng)建一個新的線程就是給進程增加了一個執(zhí)行流,執(zhí)行流總得有要執(zhí)行的代碼吧,所以新建一個線程需要提供一個函數(shù)或者方法作為線程的入口。

1.使用NSThread

NSThread提供了創(chuàng)建線程的途徑,還可以提供了檢測當前線程是否是主線程的方法。 使用NSThread創(chuàng)建一個新的線程有兩種方式:

  • 1.創(chuàng)建一個NSThread的對象,調(diào)用其start方法。對于這種方式的NSThread對象的創(chuàng)建,可以使用一個目標對象的方法初始化一個NSThread對象,或者創(chuàng)建一個繼承NSThread類的子類,實現(xiàn)其main方法,然后在直接創(chuàng)建這個子類的對象。
  • 2.使用 detachNewThreadSelector:toTarget:withObject:這個類方法創(chuàng)建一個線程,這個比較直接了,直接使用目標對象的方法作為線程啟動入口。

2.使用NSObject

其實NSObject直接就加入了多線程的支持,允許對象的某個方法在后臺運行。如:

  1. [myObj performSelectorInBackground:@selector(doSomething) withObject:nil]; 

3.POSIX Thread

由于Mac和iOS都是基于Darwin系統(tǒng),Darwin系統(tǒng)的XUN內(nèi)核,是基于Mach和BSD的,繼承了BSD的POSIX接口,所以可以直接使用POSIX線程的相關接口來使用線程。

創(chuàng)建線程的接口為 pthread_create,當然在創(chuàng)建之前可以通過相關函數(shù)設置好線程的屬性。以下為POSIX線程使用簡單的例子。

  1. // //  main.c //  pthread // //  Created by Lu Kejin on 1/27/12. //  Copyright (c) 2012 Taobao.com. Al 

 

三.多線程進階

NSOperation&NSOperationQueue

很多時候我們使用多線程,需要控制線程的并發(fā)數(shù),畢竟線程也是消耗系統(tǒng)資源的,當程序中同時運行的線程過多時,系統(tǒng)必然變慢。 所以很多時候我們會控制同時運行線程的數(shù)目。

NSOperation可以封裝我們的操作,然后將創(chuàng)建好的NSOperation對象放到NSOperationQueue中,OperationQueue便開始啟動新的線程去執(zhí)行隊列中的操作,OperationQueue的并發(fā)度是可以通過如下方式進行設置:

  1. - (void)setMaxConcurrentOperationCount:(NSInteger)count 

GCD

GCD是Grand Central Dispatch的縮寫,是一系列的BSD層面的接口,在Mac 10.6 和iOS4.0以后才引入的,且現(xiàn)在NSOperation和NSOperationQueue的多線程的實現(xiàn)就是基于GCD的。目前這個特性也被移植到 FreeBSD上了,可以查看libdispatch這個開源項目。

比如一個在UIImageView中顯示一個比較大的圖片

  1. dispatch_queue_t imageDownloadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(imageDownloa 

當然,GCD除了處理多線程外還有很多非常好的功能,其建立在強大的kqueue之上,效率也能夠得到保障。

 

四.線程間通信

線程間通信和進程間通信從本質(zhì)上講是相似的。線程間通信就是在進程內(nèi)的兩個執(zhí)行流之間進行數(shù)據(jù)的傳遞,就像兩條并行的河流之間挖出了一道單向流動長溝,使得一條河流中的水可以流入另一條河流,物質(zhì)得到了傳遞。

       1.performSelect On The Thread

框架為我們提供了強制在某個線程中執(zhí)行方法的途徑,如果兩個非主線程的線程需要相互間通信,可以先將自己的當前線程對象注冊到某個全局的對象中去,這樣相 互之間就可以獲取對方的線程對象,然后就可以使用下面的方法進行線程間的通信了,由于主線程比較特殊,所以框架直接提供了在出線程執(zhí)行的方法。

  1. @interface NSObject (NSThreadPerformAdditions) - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUnti 

       2.Mach Port 
在蘋果的Thread Programming Guide的Run Pool一節(jié)的Configuring a Port-Based Input Source 這一段中就有使用Mach Port進行線程間通信的例子。 其實質(zhì)就是父線程創(chuàng)建一個NSMachPort對象,在創(chuàng)建子線程的時候以參數(shù)的方式將其傳遞給子線程,這樣子線程中就可以向這個傳過來的 NSMachPort對象發(fā)送消息,如果想讓父線程也可以向子線程發(fā)消息的話,那么子線程可以先向父線程發(fā)個特殊的消息,傳過來的是自己創(chuàng)建的另一個 NSMachPort對象,這樣父線程便持有了子線程創(chuàng)建的port對象了,可以向這個子線程的port對象發(fā)送消息了。

當然各自的port對象需要設置delegate以及schdule到自己所在線程的RunLoop中,這樣來了消息之后,處理port消息的delegate方法會被調(diào)用,你就可以自己處理消息了。

 

五.RunLoop

RunLoop從字面上看是運行循環(huán)的意思,這一點也不錯,它確實就是一個循環(huán)的概念,或者準確的說是線程中的循環(huán)。 本文一開始就提到有些程序是一個圈,這個圈本質(zhì)上就是這里的所謂的RunLoop,就是一個循環(huán),只是這個循環(huán)里加入很多特性。 
首先循環(huán)體的開始需要檢測是否有需要處理的事件,如果有則去處理,如果沒有則進入睡眠以節(jié)省CPU時間。 所以重點便是這個需要處理的事件,在RunLoop中,需要處理的事件分兩類,一種是輸入源,一種是定時器,定時器好理解就是那些需要定時執(zhí)行的操作,輸 入源分三類:performSelector源,基于端口(Mach port)的源,以及自定義的源。編程的時候可以添加自己的源。RunLoop還有一個觀察者Observer的概念,可以往RunLoop中加入自己的 觀察者以便監(jiān)控著RunLoop的運行過程,CFRunLoop.h中定義了所有觀察者的類型:

  1. enum CFRunLoopActivity { kCFRunLoopEntry = (1 << 0), kCFRunLoopBeforeTimers = (1 << 1), kCFRunLoopBeforeSources = ( 

如果你使用過select系統(tǒng)調(diào)用寫過程序你便可以快速的理解runloop事件源的概念,本質(zhì)上講事件源的機制和select一樣是一種多路復用IO的 實現(xiàn),在一個線程中我們需要做的事情并不單一,如需要處理定時鐘事件,需要處理用戶的觸控事件,需要接受網(wǎng)絡遠端發(fā)過來的數(shù)據(jù),將這些需要做的事情統(tǒng)統(tǒng)注 冊到事件源中,每一次循環(huán)的開始便去檢查這些事件源是否有需要處理的數(shù)據(jù),有的話則去處理。 拿具體的應用舉個例子,NSURLConnection網(wǎng)絡數(shù)據(jù)請求,默認是異步的方式,其實現(xiàn)原理就是創(chuàng)建之后將其作為事件源加入到當前的 RunLoop,而等待網(wǎng)絡響應以及網(wǎng)絡數(shù)據(jù)接受的過程則在一個新創(chuàng)建的獨立的線程中完成,當這個線程處理到某個階段的時候比如得到對方的響應或者接受完 了網(wǎng)絡數(shù)據(jù)之后便通知之前的線程去執(zhí)行其相關的delegate方法。所以在Cocoa中經(jīng)常看到scheduleInRunLoop:forMode: 這樣的方法,這個便是將其加入到事件源中,當檢測到某個事件發(fā)生的時候,相關的delegate方法便被調(diào)用。對于CoreFoundation這一層而 言,通常的模式是創(chuàng)建輸入源,然后將輸入源通過CFRunLoopAddSource函數(shù)加入到RunLoop中,相關事件發(fā)生后,相關的回調(diào)函數(shù)會被調(diào) 用。如CFSocket的使用。 另外RunLoop中還有一個運行模式的概念,每一個運行循環(huán)必然運行在某個模式下,而模式的存在是為了過濾事件源和觀察者的,只有那些和當前 RunLoop運行模式一致的事件源和觀察者才會被激活。

每一個線程都有其對應的RunLoop,但是默認非主線程的RunLoop是沒有運行的,需要為RunLoop添加至少一個事件源,然后去run它。一般情況下我們是沒有必要去啟用線程的RunLoop的,除非你在一個單獨的線程中需要長久的檢測某個事件。

責任編輯:閆佳明 來源: oschina
相關推薦

2010-03-10 19:25:04

python多線程

2024-08-28 08:00:00

2024-10-18 16:58:26

2011-07-22 14:55:20

多線程

2021-04-30 11:45:20

iOSRunLoop監(jiān)控

2013-07-16 10:12:14

iOS多線程多線程概念多線程入門

2015-07-22 09:39:38

IOS多線程同步

2016-04-12 09:48:24

nsthread多線程ios

2011-08-02 10:26:59

iOS 多線程 線程

2015-07-22 09:51:51

iOS開發(fā)線程

2013-07-16 10:57:34

iOS多線程多線程概念多線程入門

2010-01-18 14:09:58

C++多線程

2013-07-16 12:13:27

iOS多線程多線程概念GCD

2013-07-15 15:35:06

2014-07-21 10:03:56

2024-10-14 16:25:59

C#線程鎖代碼

2010-03-17 19:24:38

Java多線程循環(huán)

2010-03-17 14:58:20

Java多線程

2010-03-19 17:47:02

Java Socket

2013-07-16 13:39:11

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 色屁屁在线观看 | 日韩在线小视频 | 91久久精品日日躁夜夜躁欧美 | av特级毛片 | 99精品视频在线观看免费播放 | 国产成人高清 | 女女百合av大片一区二区三区九县 | 亚洲精品国产电影 | 天堂中文在线播放 | 亚洲欧美在线观看视频 | 在线国产一区 | 九九热在线视频 | 国产xxxx岁13xxxxhd | 国产小视频在线 | 91九色视频| 成人国产在线视频 | 欧美一区二区成人 | 亚洲精品在线免费看 | 中文字幕在线一区二区三区 | 少妇午夜一级艳片欧美精品 | 国产伦精品一区二区三区照片91 | 一区观看| 午夜看看 | 亚洲国产片 | 欧美在线日韩 | gav成人免费播放视频 | 中文字幕在线第一页 | 国产在线网站 | 亚洲天堂色 | 91在线观看 | 亚洲免费人成在线视频观看 | 国产小视频在线 | 国产在线一区二区 | 草草视频在线播放 | 日韩亚洲一区二区 | 中文字幕综合 | 黄色亚洲 | 在线观看国产www | 免费一区在线观看 | 欧美日韩在线免费观看 | 欧美一区二区网站 |