2、Thread —— swift3.0

Swift3.0 中的 Thread 類
其實(shí)就是 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í)行的線程
    // 通過(guò)當(dāng)前線程的 number 屬性, number == 1 的時(shí)候?yàn)閱尉€程, number > 1 的時(shí)候是多線程, number 的數(shù)字沒(méi)有很多的參考價(jià)值
    public class func current() -> Thread

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

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

    
    public var threadDictionary: NSMutableDictionary { get }

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

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


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

    @available(iOS 4.0, *)
    // 設(shè)置線程的級(jí)別, 已經(jīng)被棄用,請(qǐ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, *)
    // 線程的符號(hào)
    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, *)
    // 開(kāi)始線程
    public func start()

    
    @available(iOS 2.0, *)
    // 線程主體方法,這個(gè)方法一般是用來(lái)重寫的
    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 的類擴(kuò)展
// 意味著所有的 NSObject 對(duì)象都可以使用下面的方法
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, *)
    // 在某個(gè)線程執(zhí)行某方法
    public func perform(_ aSelector: Selector, on thr: Thread, with arg: AnyObject?, waitUntilDone wait: Bool, modes array: [String]?)

    @available(iOS 2.0, *)
    // 在某個(gè)線程執(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?)
}

上面貼頭文件純屬個(gè)人喜好,本人簡(jiǎn)單翻譯為的是后期的被查,解決英文不好的毛病。


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

Thread.current() number 為 1 的時(shí)候是主線程,線程數(shù)不為1 就為多線程。數(shù)子沒(méi)有意義。

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)建一個(gè)線程對(duì)象 
 let thread1 = Thread(target: self, selector: #selector(longOperation), object: "thread1")

 //  線程默認(rèn)是不會(huì)啟動(dòng)的
 //  必須我們手動(dòng)啟動(dòng)
 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)建了一個(gè)線程對(duì)象
// 這樣創(chuàng)建的線程操作性太小
// 我們一般會(huì)使用上面的方法
let thread  = Thread()

通過(guò) Thread 直接分離(創(chuàng)建)一個(gè)線程執(zhí)行某個(gè)方法。
使用這種方式創(chuàng)建的線程,線程是直接啟動(dò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)}

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

使用 NSObject 的方法直接在后臺(tái)線程執(zhí)行某方法
(實(shí)際上也是創(chuàng)建一個(gè)新的線程對(duì)象,并啟動(dò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 對(duì)象都可以開(kāi)啟子線程。(都具有開(kāi)啟線程的能力)

3、線程屬性

線程名稱

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

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

線程堆棧大小

Thread.current().stackSize

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

線程的??臻g大小是 統(tǒng)一都是 512 k, 大小是可以修改。

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

線程的優(yōu)先級(jí)

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

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

多線程開(kāi)發(fā)注意

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

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

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

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

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

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

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

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


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

    // object 參數(shù)對(duì)象可以用來(lái)進(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}

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

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


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

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

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

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

    // 模擬的耗時(shí)操作
    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í)行后臺(tái)線程
(我個(gè)人比較喜歡這種方式)

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

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

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


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

    // 模擬的耗時(shí)操作
    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)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容