Grand Central Dispatch简称GCD,苹果官方推荐开发者使用的首选多线程解决方案

 实际应用

因为Alamofire已经实现异步请求功能,所以没法实践这个界面当时我在设计时候(T.T因为做的不好看被一起开发的室友吐槽然后改掉了一部分)是直接将数据存储沙盒目录下的test.plist文件里面,所以可以将他来变为异步请求

以下是具体实现

model数据为空时,调用initData方法异步请求文件里的数据,不影响UI的刷新

    override func viewDidLoad() {
        super.viewDidLoad()
        if(bodydata.count==0){
            initData()
        }
        configUI()
        configNavbar()
    }

 initData实现,首先定义一个并行队列队列添加异步任务请求数据请求结束之后切换主线刷新UI(因为UI刷新任务都必须放在主线程,不然会报错)。

    func initData(){
        let Queue = DispatchQueue(label: "task",attributes: .concurrent)
        Queue.async {
            if(plistdata?.count == nil)
            {
                let array:NSMutableArray = NSMutableArray()
                for item in origindata{
                    let dictionary:NSMutableDictionary = [ : ]
                    let center = item.centerText as NSString
                    dictionary.setValue(center, forKey: "centerText")
                    array.add(dictionary)
                }
                array.write(toFile: filePath, atomically: false)
                bodydata = origindata
            }
            else
            {
                for item in plistdata!{
                            let data = item as! NSDictionary
                            let center = data.value(forKey: "centerText") as! String
                            let sss = EditModel(centerText: center)
                            if(bodydata.count == 5)
                            {
                                break
                            }
                            else
                            {
                                bodydata.append(sss)
                            }
                        }
            }//切换主线程刷新UI
            DispatchQueue.main.async {
                self.tableview.reloadData()
            }
        }
    }

基础认识

首先是队列调度方式并行串行

并行:在本文中指并行队列多个任务放在并行队列执行可以同时运行

串行:在本文中指串行队列多个任务放在串行队列执行,只能按顺序依次运行,前一个运行完成,下一个才能开始运行;前一个运行完,后一个只能排队等着。以此类推,直到所有任务运行完成。

                                                   并行

               

                                                   并发

任务执行方式同步异步

同步同步执行任务,在一个线程当中必须按顺序执行执行结束的顺序也是固定的,而且同步任务阻塞当前线程,直到同步任务结束才会结束阻塞同步任务会经常造成线程的循环等待而导致死锁,慎用。

异步异步执行任务,也是按顺序执行多项任务,但是是放在多个线程里同时运行,线程当中各个任务的开始执行时间和任务结束时间固定,总耗时大约是耗时最长的那项任务所消耗的时间

调度队列的种类:主队列,全局队列,自定义串行队列,自定义并行队列。

主队列(Main queue串行队列):UI刷新的相关操作必须放在主队列

let mainQueue = DispatchQueue.main

全局队列(Global queue,并行队列):运行后台线程,是系统共享全局队列,是一种并行队列(Concurrent),用于处理并发任务。因为是系统共享,不单单属于这一个app,所以栅栏函数全局列中无效,为了避免堵塞其他程序的任务。

    1,全局队列没有名字,但是并发队列有名字。有名字以便查看系统日志

    2,全局队列是所有应用程序共享的。

    3,在mrc时候,全局队列不用手动释放,但是并发队列需要

let globalQueue = DispatchQueue.global()

自定义串行/并行队列(Custom queue):同样运行在后台。

//串行队列,label后为队列名字
let serialQueue = DispatchQueue(label: "fmy")

//并行队列
let concurrentQueue = DispatchQueue(label: "fmy", attributes: .concurrent)

线程调度优先级(Qos

优先级低的任务要等优先级高的执行完,即使是并行队列。

基础使用

//定义2个调度任务,打印当前线程数据
let item1 = DispatchWorkItem {
    for i in 0...4{
        print("item1 -> (i)  thread: (Thread.current)")
    }
}

let item2 = DispatchWorkItem {
    for i in 0...4{
        print("item2 -> (i)  thread: (Thread.current)")
    }
}
//主队列追加异步任务,按顺序打印
let mainQueue = DispatchQueue.main
mainQueue.async(execute: item1)
mainQueue.async(execute: item2)


//全局队列追加异步任务,随机打印
let globalQueue = DispatchQueue.global()
globalQueue.async(execute: item1)
globalQueue.async(execute: item2)


//自定义串行队列追加异步任务,按顺序打印
let serialQueue = DispatchQueue(label: "serial")
serialQueue.async(execute: item1)
serialQueue.async(execute: item2)


//自定义并行队列追加异步任务,随机打印
let concurrentQueue = DispatchQueue(label: "concurrent", attributes: .concurrent)
concurrentQueue.async(execute: item1)
concurrentQueue.async(execute: item2)

//主队列追加同步任务,会引起死锁
let mainQueue = DispatchQueue.main
mainQueue.sync(execute: item1)
mainQueue.sync(execute: item2)

//全局队列追加同步任务,按顺序打印
let globalQueue = DispatchQueue.global()
globalQueue.sync(execute: item1)
globalQueue.sync(execute: item2)

//自定义串行队列追加同步任务,按顺序打印
let serialQueue = DispatchQueue(label: "serial")
serialQueue.sync(execute: item1)
serialQueue.sync(execute: item2)

//自定义并行队列追加同步任务,按顺序打印
let concurrentQueue = DispatchQueue(label: "concurrent", attributes: .concurrent)
concurrentQueue.sync(execute: item1)
concurrentQueue.sync(execute: item2)

死锁情况

1.主队列加入同步任务

2.串行队列当中的同步任务或者异步任务当中又嵌套了一个同步任务

原因分析假设正在执行的任务是A任务(不管同步异步),A任务当中加入一个同步任务B(B任务属于A任务的一部分),要想执行完A任务,必须先执行B任务(因为同步任务阻塞线程),而调度队列又属于串行队列,A排在B前边,所以必须等任务A执行完才能执行任务B,这样就造成了循环等待,形成死锁。

//主队列添加同步任务
let mainQueue = DispatchQueue.main
mainQueue.sync(execute: item1)//同步任务
//自定义的串行队列
let serialQueue = DispatchQueue(label: "serial")
//死锁
serialQueue.sync {
    print("同步执行  thread: (Thread.current)")
    serialQueue.sync {
        print("同步执行  thread: (Thread.current)")
    }
}
//死锁
serialQueue.async {
    print("异步执行  thread: (Thread.current)")
    serialQueue.sync {
        print("同步执行  thread: (Thread.current)")
    }
}

3.不过自定义串行队列只加入同步任务不会导致死锁。煮个栗子:假如现在主线程在执行任务A(A任务在主队列当中),而串行队列加入了一个同步任务B,不管是什么队列加入同步任务,这个任务都会放到主线程去执行(分析见下文),所以这个时候,要想执行任务A,必须先执行任务B,而这个时候任务B可不可以执行呢?答案可以,因为任务B在自定义的串行队列里面,而任务A在其他队列里面,这个时候任务B并没有被A给阻塞啊,所以是可以运行的,不会死锁。(所以说死锁针对的是队列,不是线程)

其他队列的同步任务也会放到主线程执行:

print("=> 开始执行")

let mainQueue = DispatchQueue.main
mainQueue.async(execute: item1)//异步任务

print("=> 执行完毕1")

let globalQueue = DispatchQueue.global()
globalQueue.sync(execute: item2)//同步任务

运行结果:
=> 开始执行
=> 执行完毕1
item2 -> 0  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item2 -> 1  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item2 -> 2  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item2 -> 3  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item2 -> 4  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
=> 执行完毕2
item3 -> 0  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item3 -> 1  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item3 -> 2  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item3 -> 3  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item3 -> 4  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
//用户的串行队列加入同步任务也是在主线程执行
let serialQueue = DispatchQueue(label: "serial")
serialQueue.sync(execute: item2)//同步任务

结果:
item2 -> 0  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item2 -> 1  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item2 -> 2  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item2 -> 3  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}
item2 -> 4  thread: <NSThread: 0x7fbf2cc0e7e0>{number = 1, name = main}

参考文章详解Swift多线程 | licc

一天精通iOS Swift多线程(GCD) – 掘金

原文地址:https://blog.csdn.net/qq_55655826/article/details/123543692

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_30974.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注