對耗時操作的理解
//注意:如果將耗時操作放到主線程中,會將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
}