NSThread三種創建線程的方法

對耗時操作的理解


//注意:如果將耗時操作放到主線程中,會將UI界面卡死

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //打印當前線程
        print("viewDidLoad:\(NSThread.currentThread())")
    }
    
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //打印當前線程
        //number:線程標號(標號為1的線程是主線程,標號大于1的線程都是子線程)
        //name:線程名
        print("touchesBegan:\(NSThread.currentThread())")
        
        self.longTimeOperation()
    }

   
    //MARK: - 耗時操作
    func longTimeOperation() {
        
        for _ in 0...200000 {
            
            print(NSDate())
            //打印當前線程
            print("longTimeOperation:\(NSThread.currentThread())")
        }
    }

}

NSThread基礎

class ViewController: UIViewController {

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //創建子線程
        self.creatThread4()
    }
    

    //MARK: - 耗時操作
    func longTimeOperation() {
        
        for _ in 0...1000000 {
            
            //阻塞1秒
            //NSThread.sleepForTimeInterval(1)
            
            print(NSDate())
            print(NSThread.currentThread())
        }
        
        //耗時操作執行完成后將子線程取消
        NSThread.currentThread().cancel()
    }
    
    //耗時操作2
    func longTimeOperation2(){
    
        for _ in 0...1000000 {
            
            //阻塞1秒
            //NSThread.sleepForTimeInterval(1)
            
            print(NSDate())
            print(NSThread.currentThread())
        }
    }

}


//MARK: - 線程屬性
extension ViewController{

    
    func creatThread4() {
        
        // - 第一個子線程
        //1.創建線程對象
        let threadA = NSThread.init(target: self, selector: "longTimeOperation", object: nil)
        //2.設置線程名
        threadA.name = "線程A"
        //3.設置優先級(默認是0.5),優先級影響的并不是那個線程先被執行,而影響的是CPU調度子線程的時候停留時間(時間片) -> 一般不設置
        threadA.threadPriority = 0.1
        
        //4.!!!獲取當前線程
        let thread =  NSThread.currentThread()
        print("當前線程:\(thread)")
        //5.!!!獲取主線程
        let mainThread = NSThread.mainThread()
        print("主線程:\(mainThread)")
        
        
        //啟動線程
        threadA.start()
        
        
        // - 第二個子線程
        let threadB = NSThread.init(target: self, selector: "longTimeOperation2", object: nil)
        //設置線程名
        threadB.name = "線程B"
        
        //設置優先級
        threadB.threadPriority = 0.9
        
        //啟動線程
        threadB.start()
        
        
    }
}


//MARK: - 子線程的創建方式
extension ViewController{
    
    //- 方式3:隱式的創建一個子線程
    func creatThread3() {
        //1.創建一個后臺線程(子線程),創建好之后會自動啟動
        self.performSelectorInBackground("longTimeOperation", withObject: nil)
    }
    
    //- 方式2:快速創建一個子線程
    func creatThread2() {
        
        //1.創建子線程對象,但是線程對象不會被返回;創建好之后會自動啟動
        NSThread.detachNewThreadSelector("longTimeOperation", toTarget: self, withObject: nil)
    }
    

    //- 方式1
    func creatThread1()  {
        //1.創建子線程對象
        let thread = NSThread.init(target: self, selector: "longTimeOperation", object: nil)
        //3.啟動線程
        thread.start()
    }
    
}

線程控制

class ViewController: UIViewController {

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
        //1.新建 -> 在內存中開辟空間存儲對象
        let thread = NSThread.init(target: self, selector: "longTimeOperation", object: nil)
        
        //2.就緒-運行 -> 線程對象被添加到了可調用線程池中,當CPU調度到當前的線程,那么當前線程處于運行狀態,否則就是就緒狀態
        //注意:CPU只能調度在可調度線程池中的線程
        thread.start()
    }

    
    //MARK: - 耗時操作
    func longTimeOperation() {
        
        for item in 0...10 {
        
            if item == 5 {
                
                //3.阻塞 -> 線程從可調度線程池中移除,但是在內存中還存在。讓睡眠時間到了,被移除的線程,會重新添加到可調度線程池中
                //讓當前線程睡眠1秒
                NSThread.sleepForTimeInterval(2)
            }
            
            if item == 9 {
                
                //4.強制死亡
                NSThread.exit()
            }
            
            
            print(NSThread.currentThread(),item)
        }
        
        //4.死亡 -> 從可調度線程池中移除,并且從內存中銷毀
        print("自然死亡")
        
    }
}

線程安全

class ViewController: UIViewController {
    //MARK: - 屬性
    //票數
    var tickets = 20
    //創建一個鎖對象
    let lock = NSLock.init()
    
    

    //MARK: - 方法
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
        //創建兩個線程去賣票
        let threadA = NSThread.init(target: self, selector: "sellTickets", object: nil)
        threadA.name = "售票點1"
        threadA.start()
        
        let threadB = NSThread.init(target: self, selector: "sellTickets", object: nil)
        threadB.name = "售票點2"
        threadB.start()
    }

    
    //MARK: - 賣票
    func sellTickets() {
        
        while true {
            
            //1.加鎖:
            //在lock()到unlock()之間的代碼,帶一個線程執行的時候,另外的線程是沒有辦法執行的
            self.lock.lock()
            
            //賣票過程
            NSThread.sleepForTimeInterval(1)
            
            if self.tickets > 0 {
                self.tickets -= 1
                print("\(NSThread.currentThread())余票:\(self.tickets)張")
                
            }else{
            
                print("票賣完了")
                //票賣完之后讓賣票的線程全部死亡
                NSThread.exit()
            }
        
            //2.解鎖
            self.lock.unlock()
            
        }
    }
}

線程間同行

 //MARK: - 屬性
    @IBOutlet weak var imageView: UIImageView!
    
    //MARK: - 方法
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        
        //在子線程中去下載圖片
        self.performSelectorInBackground("downloadImage", withObject: nil)
        
    }
    
    //MARK: - 下載圖片
    func downloadImage(){
        
        print("下載圖片:\(NSThread.currentThread())")
        
        //圖片路徑
        let imagePath = "http://img2.imgtn.bdimg.com/it/u=2565691122,4106397048&fm=11&gp=0.jpg"
        
        //將圖片地址轉換成url
        let url = NSURL.init(string: imagePath)
        
        //下載圖片(耗時操作)
        let data = NSData.init(contentsOfURL: url!)
        
        //將二進制轉換成圖片
        let image = UIImage.init(named: "10_12.jpg")
        
        print("圖片下載完成")
        
        
        //!!!圖片下載完成后回到主線程去展示圖片
        //參數1:指定的方法
        //參數2:指定的線程
        //參數3:方法中的實參
        //參數4:是否等待指定的方法執行完成
        //功能:在指定的線程中調用指定的方法
        self.performSelector("showImage:", onThread: NSThread.mainThread(), withObject: image, waitUntilDone: false)
        
        
        
    }
    //MARK: - 顯示圖片
    func showImage(image:UIImage) {
        
        print("顯示圖片:\(NSThread.currentThread())")

        self.imageView.image = image
    }
    

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 本文選譯自《Threading Programming Guide》。 導語 線程技術作為在單個應用程序中并發執行...
    巧巧的二表哥閱讀 2,470評論 4 24
  • Object C中創建線程的方法是什么?如果在主線程中執行代碼,方法是什么?如果想延時執行代碼、方法又是什么? 1...
    AlanGe閱讀 1,793評論 0 17
  • 又吵架了,已經不記得這是第幾次的爭吵。每次都許諾下次不會再犯,可是一再再的忍讓換來的只是愈演愈烈,吱吱有點招架不住...
    劉二丫兒閱讀 624評論 0 0