swift的多线程学习 

同OC一样,分三者来学习,Thread,Operation和GCD 

首先:Thread 每个对象对应一个线程,优点是量级较轻,使用简单,缺点是需要开发者自行管理线程的生命周期,线程同步,加锁解锁,睡眠以及唤醒灯操作 

其次:Operation技术上不需要关心线程的管理和线程同步的事情,只需要关系业务的处理逻辑,缺点是只能实现它或者使用它的定义好的子类 

最后:就是实际应用最多的GCD了,实际上它是底层的API。很强大,不仅仅决定代码块在哪一个线程中被执行,而且还可以根据可用的系统资源对这些线程进行处理

接下来就说一些简单的例子来说明: 

Thread

        开辟子线程下载图片,然后回到主线程进行刷新

(frame:CGRect(x:0,y:260,width:320,height:300))
(imageView)
 
(frame:CGRect(x:0,y:0,width:320,height:300))
        label.backgroundColor = UIColor.white
        label.textAlignment = .center
        label.text = "Loading..."
(ofSize: 40)
(label)
 
        let imageURL = "http://images.apple.com/v/iphone/home/s/home/images/trade_in_iphone_large_2x.jpg"
(target:self, selector:#selector(ViewController.downloadImage),object:imageURL)
()
 
 
@objc func downloadImage(path:String) {
(string:path)
        var data:Data!
        do{
(contentsOf:url!)
(data:data)
(#selector(ViewController.showImage),on:Thread.main,with:image,waitUntilDone:true)
        }catch{
("xiazaishibai")
        }

 因为我们要下载图片,如果放置在主线程上,就会影响当前的主线程,显示速度很慢。我们就将这个下载的任务,单独去开辟一个字线程,让它在子线程中下载,下载结束以后,然后刷新一下主线程就显示出来了,也不会对主线程造成阻塞的现象。 

如果遇到多个字线程的问题,我们就需要开辟多个线程,然后同时需要加锁,这样就不会出现资源被重复利用的情况,比如我们现实生活中的购票操作。同时几个窗口售票问题。

(target:self,selector:#selector(ViewController.sellBook),object:nil)
售货员A"
();
        
(target:self,selector:#selector(ViewController.sellBook),object:nil)
售货员B"
();
        
(target:self,selector:#selector(ViewController.sellBook),object:nil)
售货员C"
();
 
 
@objc func sellBook(){
        while true {
  //如果在这里不做一个加锁的处理就会造成资源被重复利用的情况,这里加锁以后每次只能有一个字线程执行操作
            if bookCounts>0 {
(forTimeInterval: 0.01)
               soldBookCounts+=1
                bookCounts-=1
                let ThreadName = Thread.current.name
("当前销售员为:\(ThreadName),此时售卖掉书:\(soldBookCounts),还剩下\(bookCounts)本")
 
                
            }else{
()
            }
()
        }
        
    }

Operation

如果我们需要同时下载几张照片,我们采用Operation的话,首先我们一般采用的是Operation的子类BlockOperation,然后我们将这些字线程加入到OperationQueue,值得注意的是;//并发操作数,这里只要设置为1的话每次只能执行一个。 

(frame:CGRect(x:0,y:0,width:320,height:280))
(frame:CGRect(x:0,y:280,width:320,height:280))
        
(imageView1)
(imageView2)
 
(name: "下载线程A", imageUrl: "http://images.apple.com/v/watch/k/images/overview/watch_03_large.jpg", isTopOne: true)
(name: "下载线程B", imageUrl: "http://images.apple.com/v/watch/k/images/overview/watch_05_large.jpg", isTopOne: false)
        
()
;//并发操作数
(downloadA)
(downloadB)
   
        for operation in queue.operations {
("Operation名称:"+operation.name!)
        }
 
 
 
(name:String,imageUrl:String,isTopOne:Bool)->BlockOperation{
(block:{
(string:imageUrl)
            var data:Data!
            do{
(forTimeInterval: 1.0)
(contentsOf:url!)
(data:data)
                if isTopOne{
(#selector(ViewController.showTopImage), on: Thread.main, with: image, waitUntilDone: true)
                }else{
(#selector(ViewController.showFootImage), on: Thread.main, with: image, waitUntilDone: false)
                }
                
            }catch{
("下载图片失败")
            }
)
        download.name = name
        return download
    }
 
(image:UIImage){
        self.imageView1.image = image
    }
 
(image:UIImage) {
        self.imageView2.image = image
    }

GCD的使用

UI刷新的操作

(x:0,y:0,width:320,height:568)
        label.text = "loading..."
(name:"Arial",size:24)
;
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
(label)
 
(string:"http://ip.taobao.com/service/getIpinfo.php?ip=27.156.152.57")
 
()//创建一个全局变量,它是并发队列
在block里面执行需要的查询任务
(contentsOf:apiUrl!)
(result==nil){
回到主线程刷新UI
解析不出来"
                }
            }else
            {
(data:result!,encoding:String.Encoding.utf8)
                DispatchQueue.main.async {
                    self.label.text = message
                }
 
            }
 
        }

DispatchGroup 调度组的使用,实际上就是一个线程组,我们可以分别在不同的线程中执行不同的任务,当任务执行结束以后我们可以做一个通知的处理

//首先在界面上放置一个标签
(x:0,y:0,width:320,height:568)
        label.text = "loading..."
(name:"Arial",size:24)
;
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
(label)
        
()
()//创建一个全局队列
(group: group, execute: {
("执行任务一")
)
        
(group: group, execute: {
("执行任务二")
)
        
(group: group, execute: {
("执行任务三")
)
        
(queue: globalQueue, execute: {
UI的处理
(" 任务都执行结束")
            DispatchQueue.main.async {
()
            }
)