2、Thread —— swift3.0

Swift3.0 中的 Thread 類
其實就是 NSThread

import CoreFoundation
import CoreGraphics
import Darwin
import Darwin.uuid
import Foundation

/*  NSThread.h
    Copyright (c) 1994-2015, Apple Inc. All rights reserved.
*/
// 在 swift 3.0 中  NSThread 被修改我 Thread
public class Thread : NSObject {

    // 獲取當(dāng)前執(zhí)行的線程
    // 通過當(dāng)前線程的 number 屬性, number == 1 的時候為單線程, number > 1 的時候是多線程, number 的數(shù)字沒有很多的參考價值
    public class func current() -> Thread

    // 分離出新線程, 類方法, (直接創(chuàng)建一個線程對象,并開啟線程)
    // 當(dāng)我們給需要在新線程中執(zhí)行某方法的時候可以用這個方法
    public class func detachNewThreadSelector(_ selector: Selector, toTarget target: AnyObject, with argument: AnyObject?)

    // 判斷是否是多線程
    public class func isMultiThreaded() -> Bool

    
    public var threadDictionary: NSMutableDictionary { get }

    // 線程睡(指定時間)
    public class func sleep(until date: Date)
    // 指定時間間隔
    public class func sleep(forTimeInterval ti: TimeInterval)

    // 退出線程
    public class func exit()


    // 線程的優(yōu)先級處理
    // 線程的級別
    public class func threadPriority() -> Double
    // 設(shè)置線程級別
    public class func setThreadPriority(_ p: Double) -> Bool

    @available(iOS 4.0, *)
    // 設(shè)置線程的級別孩锡, 已經(jīng)被棄用酷宵,請用下面的服務(wù)質(zhì)量
    public var threadPriority: Double // To be deprecated; use qualityOfService below

    
    @available(iOS 8.0, *)
    // 服務(wù)質(zhì)量
    public var qualityOfService: QualityOfService // read-only after the thread is started

    
    @available(iOS 2.0, *)
    // 調(diào)用堆棧返回的地址
    public class func callStackReturnAddresses() -> [NSNumber]

    @available(iOS 4.0, *)
    // 線程的符號
    public class func callStackSymbols() -> [String]

    
    @available(iOS 2.0, *)
    // 線程名稱
    public var name: String?

    
    @available(iOS 2.0, *)
    // 獲取棧內(nèi)存大小 , 默認(rèn) 512k
    public var stackSize: Int

    
    @available(iOS 2.0, *)
    // 判斷是否是主線程
    public var isMainThread: Bool { get }

    @available(iOS 2.0, *)
    // 判斷當(dāng)前線程是否是主線程
    public class func isMainThread() -> Bool // reports whether current thread is main

    @available(iOS 2.0, *)
    // 獲取主線程
    public class func main() -> Thread

    
    @available(iOS 2.0, *)
    // 初始化方法
    public init()

    @available(iOS 2.0, *)
    // 便利初始化方法
    public convenience init(target: AnyObject, selector: Selector, object argument: AnyObject?)

    
    // 線程狀態(tài)的判斷
    @available(iOS 2.0, *)
    // 線程是否執(zhí)行
    public var isExecuting: Bool { get }

    @available(iOS 2.0, *)
    // 線程是否完成
    public var isFinished: Bool { get }

    @available(iOS 2.0, *)
    // 線程是否取消
    public var isCancelled: Bool { get }

    
    @available(iOS 2.0, *)
    // 取消線程
    public func cancel()

    
    @available(iOS 2.0, *)
    // 開始線程
    public func start()

    
    @available(iOS 2.0, *)
    // 線程主體方法躬窜,這個方法一般是用來重寫的
    public func main() // thread body method
}


// 通知
extension NSNotification.Name {

    // 將要變成多線程
    public static let NSWillBecomeMultiThreaded: NSNotification.Name
    // 已經(jīng)變成單線程
    public static let NSDidBecomeSingleThreaded: NSNotification.Name
    // 線程將要推出
    public static let NSThreadWillExit: NSNotification.Name
}


// NSObject 的類擴展
// 意味著所有的 NSObject 對象都可以使用下面的方法
extension NSObject {

    // 在主線程執(zhí)行某方法
    public func performSelector(onMainThread aSelector: Selector, with arg: AnyObject?, waitUntilDone wait: Bool, modes array: [String]?)
    // 在主線程執(zhí)行某方法
    public func performSelector(onMainThread aSelector: Selector, with arg: AnyObject?, waitUntilDone wait: Bool)

    
    @available(iOS 2.0, *)
    // 在某個線程執(zhí)行某方法
    public func perform(_ aSelector: Selector, on thr: Thread, with arg: AnyObject?, waitUntilDone wait: Bool, modes array: [String]?)

    @available(iOS 2.0, *)
    // 在某個線程執(zhí)行某方法
    public func perform(_ aSelector: Selector, on thr: Thread, with arg: AnyObject?, waitUntilDone wait: Bool)

    
    @available(iOS 2.0, *)
    // 在后頭執(zhí)行選中的方法
    public func performSelector(inBackground aSelector: Selector, with arg: AnyObject?)
}

上面貼頭文件純屬個人喜好浇垦,本人簡單翻譯為的是后期的被查,解決英文不好的毛病荣挨。


1男韧、判斷當(dāng)前線程數(shù)可以知道是否是多線程朴摊。

Thread.current() number 為 1 的時候是主線程,線程數(shù)不為1 就為多線程此虑。數(shù)子沒有意義甚纲。

print(Thread.current())

打印結(jié)果
<NSThread: 0x7ff791402120>{number = 1, name = main}

objc

[NSThread currentThread];
NSLog(@"%@", [NSThread currentThread]);

打印結(jié)果:
2016-06-21 19:28:24.644 Thread-Objc[4072:1165465] <NSThread: 0x7f9e73405100>{number = 1, name = main}

使用函數(shù)判斷是否是多線程

if Thread.isMultiThreaded() {
     print("是單線程執(zhí)行")
}

objc

if (![NSThread isMultiThreaded]) {   
        NSLog(@"中是單線程!");
}

2朦前、線程的創(chuàng)建

 // 創(chuàng)建一個線程對象 
 let thread1 = Thread(target: self, selector: #selector(longOperation), object: "thread1")

 //  線程默認(rèn)是不會啟動的
 //  必須我們手動啟動
 thread1.start()

// 線程執(zhí)行的的方法
func longOperation(sender: AnyObject){
   print(sender)  // sender == thread1 
     for i in 0...50000 {
     print("\(i )" + "\(Thread.current())")
  }
}

objc

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(longOperation:) object:@"newThread"];
[thread start];

- (void)longOperation:(NSObject *)sender {
    
    NSLog(@"%@", sender);   // sender == newThread
    NSLog(@"%@", [NSThread currentThread]);
}
// 這樣就創(chuàng)建了一個線程對象
// 這樣創(chuàng)建的線程操作性太小
// 我們一般會使用上面的方法
let thread  = Thread()

通過 Thread 直接分離(創(chuàng)建)一個線程執(zhí)行某個方法介杆。
使用這種方式創(chuàng)建的線程,線程是直接啟動的

Thread.detachNewThreadSelector(#selector(longOperation), toTarget: self, with: "newThread")

// 線程執(zhí)行的方法
func longOperation(sender: AnyObject){
    print(sender)   // sender ==  newThread
   for i in 0...50 {
     print("\(i )" + "\(Thread.current())") 
    }
}
[NSThread detachNewThreadSelector:@selector(longOperation:) toTarget:self withObject:@"newThread"];
- (void)longOperation:(NSObject *)sender {

    NSLog(@"%@", sender);   // sender == newThread
    NSLog(@"%@", [NSThread currentThread]);
}

打印結(jié)果
2016-06-21 19:46:56.170 Thread-Objc[4351:1183028] newThread
2016-06-21 19:46:56.171 Thread-Objc[4351:1183028] <NSThread: 0x7f80e2c7a7b0>{number = 2, name = (null)}

一個方法里面的內(nèi)容只能在一個線程里面執(zhí)行韭寸,block 或閉包除外春哨。

使用 NSObject 的方法直接在后臺線程執(zhí)行某方法
(實際上也是創(chuàng)建一個新的線程對象,并啟動線程)

self.performSelector(inBackground: #selector(longOperation), with: "newThread")

// 線程執(zhí)行的方法
func longOperation(sender: AnyObject){
    print(sender)
    for i in 0...50 {
     print("\(i )" + "\(Thread.current())")
  }
}
[self performSelectorInBackground:@selector(longOperation:) withObject:@"newThread"];
- (void)longOperation:(NSObject *)sender {

    NSLog(@"%@", sender);   // sender == newThread
    NSLog(@"%@", [NSThread currentThread]);
}

打印結(jié)果
2016-06-21 19:46:56.170 Thread-Objc[4351:1183028] newThread
2016-06-21 19:46:56.171 Thread-Objc[4351:1183028] <NSThread: 0x7f80e2c7a7b0>{number = 2, name = (null)}

這種方式表明:
任何 NSObject 對象都可以開啟子線程恩伺。(都具有開啟線程的能力)

3赴背、線程屬性

線程名稱

// 線程名稱
public var name: String?

線程的名稱通常在大的商業(yè)應(yīng)用中,希望應(yīng)用程序上架后晶渠,捕獲到用戶使用崩潰的一些場景凰荚。
如果知道程序在哪個線程中崩潰,能夠輔助排錯乱陡。
如果線程非常多浇揩,而且在調(diào)試的時候可以起到輔助作用。

線程堆棧大小

Thread.current().stackSize

// 調(diào)整大小
Thread.current().stackSize = 1024 * 1024 

線程的椇┑撸空間大小是 統(tǒng)一都是 512 k胳徽, 大小是可以修改。

在以前的版本中 主線程是 1024k爽彤, 其他線程是 512k 养盗,大小是不能修改。

線程的優(yōu)先級

// 線程的優(yōu)先級 0 到1.0 适篙, 1 的優(yōu)先級最高往核。
// 默認(rèn)的線程優(yōu)先級是 0.5 
Thread.current().threadPriority

線程的優(yōu)先級一般不需要修改。線程的優(yōu)先級不一定決定線程的執(zhí)行循序嚷节。
(經(jīng)典例子:優(yōu)先級反轉(zhuǎn))
優(yōu)先級高只能說明 cpu 在調(diào)度的時候回優(yōu)先調(diào)度聂儒,并不意味著,優(yōu)先級低的就不會調(diào)度硫痰。

多線程開發(fā)注意

  • 優(yōu)先級只能說明 cpu 優(yōu)先調(diào)度衩婚,并不意味著優(yōu)先級低的不調(diào)度。(不要改優(yōu)先級)
  • 不能相信一次執(zhí)行的結(jié)果效斑。
  • 不要去做不同線程的比較非春。

葵花寶典:
多線程開發(fā)一定要簡單。(越復(fù)雜越不可控)

4、線程間通訊 (重點中的重點)

在子線程進(jìn)行耗時操作奇昙,在子線程完成后护侮,根據(jù)子線程的執(zhí)行結(jié)果刷新UI界面。
(有的時候储耐,不在主線程更新 UI 也不會有問題羊初。 但是一定要在主線程更新 UI)

/**
    #selector(refresUI) : 調(diào)用的方法
    with: nil  要傳遞到主線程的參數(shù)。我這里傳的是 nil 表示不傳參數(shù)弧岳。
    waitUntilDone : true  等待主線程方法執(zhí)行完畢
                              false  不等待主線程方法執(zhí)行完畢
    (說白了就是線程的串行和并行的問題凳忙, 為 true 的是線程串行业踏, false 為并行  )
*/
self.performSelector(onMainThread: #selector(refresUI), with: nil, waitUntilDone: true)

第一種創(chuàng)建線程的方式

print("befor -\(Thread.current())")
// 1. thread 對象, 在子線程中執(zhí)行耗時操作
let thread = Thread(target: self, selector: #selector(longOperation), object: nil)
        
// 2. 啟動線程
thread.start()

print("after -\(Thread.current())")


// 耗時操作
func longOperation(sender: AnyObject){
   
    // 模擬的耗時操作
    print("longOperation -\(Thread.current())")

    // object 參數(shù)對象可以用來進(jìn)行線程之間傳值
    self.performSelector(onMainThread: #selector(refresUI), with: nil, waitUntilDone: false)
}


// 刷新界面
func refresUI(){
    print("refresUI -\(Thread.current())")
}

// 打印結(jié)果
befor -<NSThread: 0x7fb0b2c059b0>{number = 1, name = main}
after -<NSThread: 0x7fb0b2c059b0>{number = 1, name = main}
longOperation -<NSThread: 0x7fb0b2f06610>{number = 3, name = (null)}
refresUI -<NSThread: 0x7fb0b2c059b0>{number = 1, name = main}

耗時操作是在子線程執(zhí)行的,刷新 ui 是在主線程執(zhí)行的

分離線程的方式
進(jìn)行了線程之間的傳值


print("befor -\(Thread.current())")

Thread.detachNewThreadSelector(#selector(longOperation), toTarget: self, with: "detachNewThread")

print("after -\(Thread.current())")

// 耗時操作
func longOperation(sender: AnyObject){

    // 模擬的耗時操作
    print("longOperation -\(Thread.current()) + 線程之間的傳遞的值:\(sender)")


    self.performSelector(onMainThread: #selector(refresUI), with: sender, waitUntilDone: false)
}


// 刷新界面
func refresUI(sender: AnyObject){
    print("refresUI -\(Thread.current()) + 線程之間的傳遞的值:\(sender)")
}

// 打印的結(jié)果
befor -<NSThread: 0x7ff3e2d06550>{number = 1, name = main}
after -<NSThread: 0x7ff3e2d06550>{number = 1, name = main}
longOperation -<NSThread: 0x7ff3e2d1e440>{number = 3, name = (null)} + 線程之間的傳遞的值:detachNewThread
refresUI -<NSThread: 0x7ff3e2d06550>{number = 1, name = main} + 線程之間的傳遞的值:detachNewThread

用 NSObject 執(zhí)行后臺線程
(我個人比較喜歡這種方式)

print("befor -\(Thread.current())")

self.performSelector(inBackground: #selector(longOperation), with: "inBackgroundThread")

print("after -\(Thread.current())")


// 耗時操作
func longOperation(sender: AnyObject){

    // 模擬的耗時操作
    print("longOperation -\(Thread.current()) + 線程之間的傳遞的值:\(sender)")


    self.performSelector(onMainThread: #selector(refresUI), with: sender, waitUntilDone: false)
}


// 刷新界面
func refresUI(sender: AnyObject){
    print("refresUI -\(Thread.current()) + 線程之間的傳遞的值:\(sender)")
}

打印結(jié)果
befor -<NSThread: 0x7f9c6ad078b0>{number = 1, name = main}
after -<NSThread: 0x7f9c6ad078b0>{number = 1, name = main}
longOperation -<NSThread: 0x7f9c6d415d90>{number = 3, name = (null)} + 線程之間的傳遞的值:inBackgroundThread
refresUI -<NSThread: 0x7f9c6ad078b0>{number = 1, name = main} + 線程之間的傳遞的值:inBackgroundThread

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市粉怕,隨后出現(xiàn)的幾起案子掠手,更是在濱河造成了極大的恐慌,老刑警劉巖伐脖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件热幔,死亡現(xiàn)場離奇詭異,居然都是意外死亡讼庇,警方通過查閱死者的電腦和手機绎巨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蠕啄,“玉大人场勤,你說我怎么就攤上這事〖吒” “怎么了和媳?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長哈街。 經(jīng)常有香客問我留瞳,道長,這世上最難降的妖魔是什么骚秦? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任她倘,我火速辦了婚禮,結(jié)果婚禮上作箍,老公的妹妹穿的比我還像新娘硬梁。我一直安慰自己,他們只是感情好蒙揣,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布靶溜。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪罩息。 梳的紋絲不亂的頭發(fā)上嗤详,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天,我揣著相機與錄音瓷炮,去河邊找鬼葱色。 笑死,一個胖子當(dāng)著我的面吹牛娘香,可吹牛的內(nèi)容都是我干的苍狰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼烘绽,長吁一口氣:“原來是場噩夢啊……” “哼淋昭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起安接,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤翔忽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盏檐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歇式,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年胡野,在試婚紗的時候發(fā)現(xiàn)自己被綠了材失。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡硫豆,死狀恐怖龙巨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情够庙,我是刑警寧澤恭应,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站耘眨,受9級特大地震影響昼榛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剔难,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一胆屿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧偶宫,春花似錦非迹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冷离。三九已至,卻和暖如春纯命,著一層夾襖步出監(jiān)牢的瞬間西剥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工亿汞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瞭空,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓疗我,卻偏偏與公主長得像咆畏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子吴裤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

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

  • 原文地址 http://www.cnblogs.com/kenshincui/p/3983982.html 大家都...
    怎樣m閱讀 1,266評論 0 1
  • 下面是我自己收集整理的Java線程相關(guān)的面試題旧找,可以用它來好好準(zhǔn)備面試。 參考文檔:-《Java核心技術(shù) 卷一》-...
    阿呆變Geek閱讀 14,762評論 14 507
  • Object C中創(chuàng)建線程的方法是什么嚼摩?如果在主線程中執(zhí)行代碼钦讳,方法是什么?如果想延時執(zhí)行代碼枕面、方法又是什么? 1...
    AlanGe閱讀 1,721評論 0 17
  • 一缚去、多線程基礎(chǔ) 基本概念 進(jìn)程進(jìn)程是指在系統(tǒng)中正在運行的一個應(yīng)用程序每個進(jìn)程之間是獨立的潮秘,每個進(jìn)程均運行在其專用且...
    AlanGe閱讀 543評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)易结,斷路器枕荞,智...
    卡卡羅2017閱讀 134,629評論 18 139