iOS多線程系統整理 swift

多線程   是一個應用程序內多個代碼的執行路徑,執行線程,同時在同一時間裏執行不一樣的任務。編程

三種:swift

一、NSTread多線程

二、Cocoa NSOperation (NSOperation,NSOperationQueue)併發

三、GrandCentralDispatch:GCD異步


1\NSTreadasync

相對最簡單,須要本身管理線程的生命週期和線程同步(加鎖會有必定的系統開銷)ide

兩種應用方式:性能

須要傳遞三個參數:spa

selector:線程執行方法""線程

target:方法所在的對象

argument:傳遞給方法的參數,可選nil

 

1、直接建立線程,自動運行線程

// Class Method

class func detachNewThreadSelector(selector:Selector,toTarget target:AnyObject,withObject argument:AnyObject?)

2、先建立一個線程對象,手動運行線程,在運行以前可設置線程優先級等信息。

convenience init(target:AnyObject,selector:Selector,object argument:AnyObject?)

 

for example

// download image method

func downloadImage()

{

var imageUrl = "https://www.baidu.com/img/bdlogo.png"

var data = NSData.dataWithContentsOfURL(NSURL.URLWithString(imageUrl),options:nil,error:nil)

println(data.length)

}

 

override func viewDidLoad(){

super.viewDidLoad()

// 第一種方式

NSThread.detachNewThreadSelector("downloadImage",toTarget:self,withObject:nil)

 

// 第二種方式

var downloadImageThread = NSThread(target:self,selector:"downloadImage",object:nil)

dowloadImageThread.start()

}

線程同步,經過鎖來實現,每一個線程有一個鎖,鎖 與 特定的線程關聯。

for example

// 定義兩個線程

var thread1,thread2:NSThread?

// 線程條件

let condition1 = NSCodition()

let condition2 = NSCodition()

// two method for thread 

func method1(sender: AnyObject)

{

  for var i = 0; i <10; i++

  {

  println("thread 1 running \(i)")

  sleep(1)

  if i == 2

  {

  thread2!.start()

// lock

condition1.lock()

condition1.wait()

condition1.unlock()

  }

  }

println(thread 1 over)

//

condition2.signal()

}

// 

func method2(sender:AnyObject)

{

  for var i=0;i<10;i++

  {

  println("thread 2 running \(i)")

  sleep(1)

  if i ==2

  {

//  active thread 1

  condition1.signal()

// lock 

condition2.lock()

condition2.wait()// stop waitting

condition2.unlock()

  }

  }

println("thread 2 over")

}

// RUN

thread2 = NSThread (target:self , selector:"method2:",object:nil)

thread1 = NSThread(target:self,selector:"method1",object:nil)

控制檯輸出

thread 1 running 0

thread 1 running 1

thread 1 running 2

thread 2 running 0

thread 2 running 1

thread 2 running 2

thread 1 running 3

thread 1 running 4

thread 1 running 5

thread 1 running 6

thread 1 running 7

thread 1 running 8

thread 1 running 9

thread 1 over

thread 2 running 3

thread 2 running 4

thread 2 running 5

thread 2 running 6

thread 2 running 7

thread 2 running 8

thread 2 running 9

 

線程1 2是同步關係,啓動2,掛起 1,激活1,掛起2,有效避免了線程1佔用一個資源時,引發線程2不能訪問的問題。


 

NSOperation 兩種方式

 兩個子類 NSInvocationOperation   NSBlockOperation

// creat instance

var operation = NSInvocationOperation(target:self,selector:"dowloadImage",object:nil)

var queue = NSOperationQueue()

queue.addOperation(operation)

後臺創建一個線程

Queue隊列中能夠加入不少個operation 能夠把它看作是一個線程池子,能夠設置線程池中的線程數,即併發操做數。

默認是:-1,-1表示沒有限制,同時運行隊列中的所有操做。

queue.maxConcurrentOperationCount = 6

// ervery operation come to an end   

var completionBlock:(()->Void)?

operation.completionBlock = completionBlock

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,4),dispatch_get_main_queue(),{println("complete")})

 

// cancell

queue.cancelAllOperations()

 

 繼承NSOperation   把子類的對象放到NSOperationQueue隊列中 ,一旦加入,就處理這個,直到操做完成,隊列被釋放。

// creat DrinkOperation.swift 繼承 NSOperation   且  實現main方法   

import UIKit

class DrinkOperation:NSOperation{

  override func main()

  {

  println("drink")

  }

 

// e.g.

// creat a  instance

var queue1 = NSOperationQueue()

// creat a operation

var drinkOperation = DrinkOperation()

// add 

queue1.addOperation(drinkOperation)


 

Grand Central Dispatch

多核編程

底層也是用線程實現,queue能夠接受任務,先到先執行順序來執行,也能夠併發或串行執行。

同步或異步

優勢多多:基於C,融入面向對象,Block,易用,性能上自動根據系統負載來增減線程數量,無需加鎖。

種方法:

本身建立隊列

func dispatch_queue_create(label:UnsafePointer<Int8>,attr:dispation_queue_attr_t!)->dispatch_queue_t!

label:參數表明隊列名稱,能夠任意名

DISPATCH_QUEUE_CONCURRENT  並行

DISPATCH_QUEUE_SERIAL 串行  

//e.g.

var serialQueue = dispatch_queue_create("serialQueue_1",DISPATCH_QUEUE_SERIAL)

var concurrentQueue = dispatch_queue_create("concurrentQueue_1",DISPATCH_QUEUE_CONCURRENT)

 獲取系統的全局隊列

func dispatch_get_global_queue(identifier:Int,flags:UInt)->dispatch_gueue_t!

參數 identifier   執行優先級  ,4個優先級

DISPATCH_QUEUE_PRIORITY_HIGH

DISPATCH_QUEUE_PRIORITY_DEFAULT

DISPATCH_QUEUE_PRIORITY_LOW

DISPATCH_QUEUE_PRIORITY_BACKGROUND    很是低的有相機,用於不太關心的後臺任務

// e.g.

var globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)

在主線程的Main dispatch queue

在主線程裏執行的隊列(只有一個主線程)

一切跟UI相關的操做都放到主線程中執行

func dispatch_get_main_queue()->dispatch_queue_t!

// e.g.

var mainQueue = dispatch_get_main_queue()


 

追加任務到隊裏的  兩個方法:
一 dispatch_async  異步追加Block

async = asynchronous 異步

func dispatch_async(queue:dispatch_queue_t!,block:dispatch_block_t!)

第一個參數:GCD隊列
第二個參數:block

// e.g.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),{()->Void in

//  耗時代碼塊

//執行完  調用主線程刷新界面

dispatch_async(dispatch_get_main_queue(),{()->Void in

//通知主線程刷新

 

})

})

 

二 dispatch_sync 同步追加Block

與以前相反,block結束以前,dispatch_sync會一直等待,等待隊列前面的全部任務完成後才執行追加的任務。

func dispatch_sync()

// e.g.

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),{()->Void in

println("sync1")

})

加到 global_queue異步隊列中,不會形成鎖死,但會一直等待代碼執行完畢。

若是加到main_queue中,在主線程中添加任務操做,就會引發死鎖。

// e.g.

dispatch_sync(dispatch_get_main_queue(),{()->Void in

print("sync2")

})


 

暫停和繼續執行隊列

func  dispatch_suspend() 暫停

func dispatch_resume() 繼續

suspend  使 suspension reference count +1

resume    -1

count>0  queue就保持掛起狀態

若是掛起了  一個 queue   或者  source    那麼銷燬他以前,先對其進行恢復。

var concurrentQueue = dispatch_queue_create("concurrentQueue_1",DISPATCH_QUEUE_CONCURRENT)

// stop

dispatch_suspend(concurrentQueue)

// go on

dispatch_resume(concurrentQueue)

只執行一次 用於單例

dispatch_once

延時:指定時間後把任務追加到 dispatch queue裏面

dispatch_after

func dispatch_time(when:XX,delta:Int64)->dispatch_time_t

delta單位很是小,到秒要乘以  NSEC_PER_SEC

let deltaT = 2.0 *Double(NSEC_PER_SEC)

let  dTime =dispatch_time(DISPATCH_TIME_NOW,Int64(deltaT))

dispatch_after(dTime,dispatch_get_global-global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)

{()->Viod in

println("延時2秒執行")

})

 

多個任務都結束的一個所有結束:dispatch_barrier_async

當執行任務更新數據時,會出現數據不同的狀況。

for i in 1...100

{

dispatch_async(queue,{()->Void in

println("\(i)")

 

})

}

雖然使用dispatch_barrier_async能夠避免

可是有另外一方法,  semaphore 信號量

var semaphore = dispatch_semaphore_creat(1)//初始值爲1

for i in 1...100

{

dispatch_async(queue,{()->Void in

 

dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER)

println("\(i)")

dispatch_semaphore_signal(semaphore)

})

}

相關文章
相關標籤/搜索