当前位置:   article > 正文

swift的多线程学习

swift的多线程学习

swift的多线程学习

 

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

 

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

 

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

 

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

 

 

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

 

Thread

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

        imageView = UIImageView(frame:CGRect(x:0,y:260,width:320,height:300))

        self.view .addSubview(imageView)

 

        label = UILabel(frame:CGRect(x:0,y:0,width:320,height:300))

        label.backgroundColor = UIColor.white

        label.textAlignment = .center

        label.text = "Loading..."

        label.font = UIFont.systemFont(ofSize: 40)

        self.view.addSubview(label)

 

        let imageURL = "http://images.apple.com/v/iphone/home/s/home/images/trade_in_iphone_large_2x.jpg"

        let thread = Thread(target:self, selector:#selector(ViewController.downloadImage),object:imageURL)

        thread.start()

 

 

@objc func downloadImage(path:String) {

        let url = URL(string:path)

        var data:Data!

        do{

            try data = Data(contentsOf:url!)

            let image = UIImage(data:data)

            self.perform(#selector(ViewController.showImage),on:Thread.main,with:image,waitUntilDone:true)

        }catch{

            print("xiazaishibai")

        }

 

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

 

 

 

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

        let salesManA = Thread(target:self,selector:#selector(ViewController.sellBook),object:nil)

        salesManA.name = "售货员A"

        salesManA.start();

        

        let salesManB = Thread(target:self,selector:#selector(ViewController.sellBook),object:nil)

        salesManB.name = "售货员B"

        salesManB.start();

        

        let salesManC = Thread(target:self,selector:#selector(ViewController.sellBook),object:nil)

        salesManC.name = "售货员C"

        salesManC.start();

 

 

@objc func sellBook(){

        while true {

            lock.lock()  //如果在这里不做一个加锁的处理就会造成资源被重复利用的情况,这里加锁以后每次只能有一个字线程执行操作

            if bookCounts>0 {

               Thread.sleep(forTimeInterval: 0.01)

               soldBookCounts+=1

                bookCounts-=1

                let ThreadName = Thread.current.name

                print("当前销售员为:\(ThreadName),此时售卖掉书:\(soldBookCounts),还剩下\(bookCounts)本")

 

                

            }else{

                Thread.exit()

            }

            lock.unlock()

        }

        

    }

 

 

 

 

Operation

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

 

        imageView1 = UIImageView(frame:CGRect(x:0,y:0,width:320,height:280))

        imageView2 = UIImageView(frame:CGRect(x:0,y:280,width:320,height:280))

        

        self.view.addSubview(imageView1)

        self.view.addSubview(imageView2)

 

        let downloadA = getOperation(name: "下载线程A", imageUrl: "http://images.apple.com/v/watch/k/images/overview/watch_03_large.jpg", isTopOne: true)

        let downloadB = getOperation(name: "下载线程B", imageUrl: "http://images.apple.com/v/watch/k/images/overview/watch_05_large.jpg", isTopOne: false)

        

        let queue = OperationQueue()

        queue.maxConcurrentOperationCount = 1;//并发操作数

        queue.addOperation (downloadA)

        queue.addOperation(downloadB)

   

        for operation in queue.operations {

            print("Operation名称:"+operation.name!)

        }

 

 

 

    func getOperation(name:String,imageUrl:String,isTopOne:Bool)->BlockOperation{

        let download = BlockOperation(block:{

            let url = URL(string:imageUrl)

            var data:Data!

            do{

                Thread.sleep(forTimeInterval: 1.0)

                try data = Data(contentsOf:url!)

                let image = UIImage(data:data)

                if isTopOne{

                    self.perform(#selector(ViewController.showTopImage), on: Thread.main, with: image, waitUntilDone: true)

                }else{

                    self.perform(#selector(ViewController.showFootImage), on: Thread.main, with: image, waitUntilDone: false)

                }

                

            }catch{

                print("下载图片失败")

            }

        })

        download.name = name

        return download

    }

 

   @objc func showTopImage(image:UIImage){

        self.imageView1.image = image

    }

 

    @objc func showFootImage(image:UIImage) {

        self.imageView2.image = image

    }

 

 

GCD的使用

        全局队列来做一个数据处理和UI刷新的操作

        label.frame = CGRect(x:0,y:0,width:320,height:568)

        label.text = "loading..."

        label.font = UIFont(name:"Arial",size:24)

        label.backgroundColor = UIColor.green;

        label.numberOfLines = 0

        label.lineBreakMode = NSLineBreakMode.byWordWrapping

        self.view.addSubview(label)

 

        let apiUrl = URL(string:"http://ip.taobao.com/service/getIpinfo.php?ip=27.156.152.57")

 

        let globalQueue = DispatchQueue.global()//创建一个全局变量,它是并发队列

        globalQueue.async {   //在block里面执行需要的查询任务

            let result = try?Data(contentsOf:apiUrl!)

            if (result==nil){

            DispatchQueue.main.async {//回到主线程刷新UI

                self.label.text = "解析不出来"

                }

            }else

            {

                let message = String(data:result!,encoding:String.Encoding.utf8)

                DispatchQueue.main.async {

                    self.label.text = message

                }

 

            }

 

        }

 

 

 

 

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

        //首先在界面上放置一个标签

        label.frame = CGRect(x:0,y:0,width:320,height:568)

        label.text = "loading..."

        label.font = UIFont(name:"Arial",size:24)

        label.backgroundColor = UIColor.green;

        label.numberOfLines = 0

        label.lineBreakMode = NSLineBreakMode.byWordWrapping

        self.view.addSubview(label)

        

        let group = DispatchGroup()

        let globalQueue = DispatchQueue.global()//创建一个全局队列

        globalQueue.async(group: group, execute: {

            print("执行任务一")

        })

        

        globalQueue.async(group: group, execute: {

            print("执行任务二")

        })

        

        globalQueue.async(group: group, execute: {

            print("执行任务三")

        })

        

        group.notify(queue: globalQueue, execute: {

            //检测到所有的任务都执行完了,我们可以做一个通知或者说UI的处理

            print(" 任务都执行结束")

            DispatchQueue.main.async {

                self.label.removeFromSuperview()

            }

        })

 

转载于:https://www.cnblogs.com/shiyong139565/p/8204941.html

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号