多線程:Operation(一)

来源:http://www.cnblogs.com/EchoHG/archive/2017/10/16/7675846.html
-Advertisement-
Play Games

1. 進程和線程 1.1 進程 進程:正在運行的應用程式叫進程 進程之間都是獨立的,運行在專用且受保護的記憶體空間中 兩個進程之間無法通訊 通俗的理解,手機上同時開啟了兩個App。這兩個App肯定是在不同的進程中的。所以這兩個App之間是獨立的,記憶體中的數據不能互相竄來竄去,兩個App之間也沒有辦法進 ...


1. 進程和線程

1.1 進程

  • 進程:正在運行的應用程式叫進程
  • 進程之間都是獨立的,運行在專用且受保護的記憶體空間中
  • 兩個進程之間無法通訊

通俗的理解,手機上同時開啟了兩個App。這兩個App肯定是在不同的進程中的。所以這兩個App之間是獨立的,記憶體中的數據不能互相竄來竄去,兩個App之間也沒有辦法進行通訊。

兩個App之間沒有辦法進行通訊?我說的是正常情況下。當然還是有不正常情況啊,例如使用iOS提供的極少數的幾種進程間通訊的工具。

1.2 線程

  • 線程:進程想要執行任務,必須要有線程,每個進程至少有一條線程。
  • 線程就是用來幹活的。
  • 程式一啟動,就會啟動進程。進程預設開啟一條線程。

幹活的線程?對啊,活太多,或者不想彼此互相等著浪費時間,當然可以找幾個人同時幹了。
例如在項目上,產品經理需求都沒有完全寫完,也不妨礙先設計一個大概的數據框架啊。例如需求沒有完全定下來,不妨礙UI童鞋提前設計啊,大不了再改嘛~ HOHO~怎麼聽上去都像是黑話。

1.3 多線程

  • 單核CPU同一時間,CPU只能處理1個線程,只有1個線程在執行任務。

  • 多線程的同時執行 : 其實是CPU在多條線程之間快速切換(調度任務)。

  • 如果CPU調度線程的速度足夠快,就造成了多線程同時執行的假象

  • 如果線程非常多,CPU會在多條線程之間不斷的調度任務,結果就是消耗了大量的CPU資源,效率下降:

    • 每個線程調度的頻率會降低
    • 線程的執行效率會下降

iPhone手機是幾核的?
A7 : iPhone 5S , 雙核
A8: iPhone 6、iPhone 6 Plus,雙核
A9:iPhone 6S、iPhone 6S Plus,雙核
A10:iPhone 7、iPhone 7 Plus,2+2核

1.4 iOS中的多線程

剛纔說了,iOS App一旦運行,預設就會開啟一條線程。這條線程,我們通常稱作為“主線程

主線程的作用:

  1. 刷新UI
  2. 處理UI事件,例如點擊、滾動、拖拽。

如果主線程的操作太多、太耗時,就會造成App卡頓現象嚴重。所以,通常我們都會把耗時的操作放在子線程中進行,獲取到結果之後,回到主線程去刷新UI。

2. Operation

 

我們來看看基礎使用:

 1 //    最基本的使用Operation
 2     private func basicOperation() {
 3 //        第一步:創建Operation
 4         let op = Operation.init()
 5 //        第二步:把要執行的代碼放入operation中
 6         op.completionBlock = {
 7         
 8             print(#function,#line,Thread.current)
 9         }
10 //        第三步:創建OperationQueue
11         let opQueue = OperationQueue.init()
12 //        第四步:把Operation加入到線程中
13         opQueue.addOperation(op)
14     }

 

使用BlockOperation創建operatoin,並直接運行。咱們看看會在哪條線程執行。

 1 //創建一個簡單的BlockOperation
 2 private func CreatBasicBlockOperation() {
 3     //使用BlockOperation創建operation
 4     let operation = BlockOperation.init {
 5         //列印,看看在哪個線程中
 6         
 7         print(#function,#line,Thread.current)
 8     }
 9     
10     //直接運行operation,看看運行在哪個線程中
11     operation.start()
12 }

 

列印一下看看運行的結果:

這就是我們說,創建完Operation如果直接運行,就會在當前線程執行。也就是說,如果實在主線程創建並且start的,那就會在主線程執行;如果是在子線程創建並且start的,那就會在子線程執行。

 

3. Basic Demo

在這個例子裡面,需求如下:
1,在子線程載入每個圖片的數據
2,圖片數據下載完畢之後,顯示出來
3,開始請求數據的時候,讓指示符開始轉動
4,所有圖片下載完畢後,指示符停止轉動

 

3. Basic Demo

在這個例子裡面,需求如下:
1,在子線程載入每個圖片的數據
2,圖片數據下載完畢之後,顯示出來
3,開始請求數據的時候,讓指示符開始轉動
4,所有圖片下載完畢後,指示符停止轉動

 

3.2 Swift中的do catch

這個是Swift和OC不一樣的地方。Swift中出現了可選值這麼一個東西,這個不是這次的重點。想深入瞭解的童鞋可以參看這篇:?和 !的使用

Swift 里有四種方法來處理錯誤:

  1. 把錯誤從函數傳遞到調用函數的代碼里
  2. 使用一個 do-catch 語句來處理錯誤
  3. 把錯誤當做一個可選值來處理
  4. 斷言這個錯誤不會發生

 

因為Demo裡面用到了do catch,那咱們就只說do catch.
在Swift的標準try中,是要配合do catch的。

下麵是do-catch語句的一般格式,如果do分句內的代碼拋出了一個錯誤,它就被catch分句捕獲,並判斷由哪個分句來處理此錯誤。

1 do {
2     try expression
3     statements
4 } catch pattern 1 {
5     statements
6 } catch pattern 2 where condition {
7     statements
8 }

3.3 優先順序

在思維導圖裡面出現了兩個優先順序。一個是屬於Operation 的,一個是屬於OperationQueue的。那咱們分看看看這兩個都是啥。

3.3.1 Operation中的優先順序

Operation裡面的這個叫做qualityOfService

1 public enum QualityOfService : Int {
2     case userInteractive
3     case userInitiated    
4     case utility    
5     case background    
6     case `default`
7 }
1 userInteractive:最高優先順序,用於用戶交互事件
2 userInitiated :次高優先順序,用於用戶需要馬上執行的事件
3 utility:普通優先順序,用於普通任務
4 background:最低優先順序,用於不重要的任務
5 default:預設優先順序,主線程和沒有設置優先順序的線程都預設為這個優先順序

 

3.3.2 operationQueue 裡面的優先順序

operationQueue中表示優先順序的屬性是queuePriority,表示操作在隊列中的優先順序。

1 public enum QueuePriority : Int {
2     case veryLow
3     case low
4     case normal
5     case high
6     case veryHigh
7 }

這些優先順序都是相對的,並不是是說必須要執行完最高的才執行次重要的。這裡面並沒有一個特別嚴格順序。只是在分配資源上有傾向性。如果隊列需要有嚴格的執行順序,還是要添加依賴關係的,這個是我們下一篇文章要分享的內容。

4. 案例實現

Operation 基本應用及優先順序小案例。
實現後效果如下:

 

 

 

這個Demo裡面,用了兩種方法創建Operation。

startBasicDemo,使用的是閉包創建Operation的方式。在startPriorityDemo裡面使用的是自定義的構造方法創建的Operation,然後把任務數組加入到線程中。

代碼:

 1 //    Operation 案例
 2     fileprivate func startBasicDemo()
 3     {
 4         let operationQueue = OperationQueue.init()
 5         operationQueue.maxConcurrentOperationCount = 3
 6         
 7         let activityIndicator = UIActivityIndicatorView()
 8         activityIndicator.startAnimating()
 9         
10         let a = UIImageView(frame: CGRect(x: 0, y: 64, width: 414, height: 100))
11         self.view.addSubview(a)
12         let b = UIImageView(frame: CGRect(x: 0, y: 164, width: 414, height: 100))
13         self.view.addSubview(b)
14         let c = UIImageView(frame: CGRect(x: 0, y: 264, width: 414, height: 100))
15         self.view.addSubview(c)
16         let d = UIImageView(frame: CGRect(x: 0, y: 364, width: 414, height: 100))
17         self.view.addSubview(d)
18         
19         
20         let imageViews = [a, b, c, d]
21         for imageView in imageViews {
22             if let url = URL(string: "https://placebeard.it/355/140")
23             {
24                 do {
25                     let image = UIImage(data:try Data(contentsOf: url))
26                     
27                     DispatchQueue.main.async
28                         {
29                             imageView.image = image
30                         }
31                 }catch
32                 {
33                     print(error)
34                 }
35             }
36         }
37 //        global queue
38         DispatchQueue.global().async
39             {
40                 [weak self] in
41 //            等待所有操作都完成了,回到主線程停止刷新器。
42 //            wait Until All Operations are finished, then stop animation of activity indicator
43                 operationQueue.waitUntilAllOperationsAreFinished()
44                 DispatchQueue.main.async
45                 {
46                     activityIndicator.stopAnimating()
47                  }
48     
49             }
50 }
View Code

 

設置了優先順序的Demo:

 1 fileprivate func startPriorityDemo() {
 2     operationQueue.maxConcurrentOperationCount = 2
 3     activityIndicator.startAnimating()
 4     
 5     var operations = [Operation]()
 6     for (index, imageView) in (imageViews?.enumerated())! {
 7         if let url = URL(string: "https://placebeard.it/355/140") {
 8             //                使用構造方法創建operation
 9             let operation = convenienceOperation(setImageView: imageView, withURL: url)
10             
11             //根據索引設置優先順序
12             switch index {
13             case 0:
14                 operation.queuePriority = .veryHigh
15             case 1:
16                 operation.queuePriority = .high
17             case 2:
18                 operation.queuePriority = .normal
19             case 3:
20                 operation.queuePriority = .low
21             default:
22                 operation.queuePriority = .veryLow
23             }
24             
25             operations.append(operation)
26         }
27     }
28     
29     //        把任務數組加入到線程中
30     DispatchQueue.global().async {
31         [weak self] in
32         self?.operationQueue.addOperations(operations, waitUntilFinished: true)
33         DispatchQueue.main.async {
34             self?.activityIndicator.stopAnimating()
35         }
36     }
37     
38 }
View Code

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>隨機點名</title> <style type="text/css"> td{ text-align: center; } </style></head><bod ...
  • 一般阿裡社招都是招3-5年的P6+高級工程師,當初自己一年經驗也沒有想過有這個面試機會。 雖然沒想著換工作,但是經常關註一些招聘網站的信息,某一天,在某boss上有個人找我,叫我發一下簡歷,我一看是阿裡的某技術專家,雖然之前也有阿裡的在某boss上給我要簡歷,但是我深知自己經驗不足,然後給boss說 ...
  • 1、內高度、內寬度: 內邊距 + 內容框 clientWidth clientHeight 2、外高度,外寬度: 邊框 + 內邊距 + 內容框 offsetWidth offsetHeight 3、上邊框、左邊框 clientTop clientLeft 4、元素的大小及其相對於視口的位置 getB ...
  • 利用css3 transform屬性刻畫鐘錶的的刻度以及指針的角度,代碼如下: ...
  • 1. Operation 設置依賴關係 先看看如何設置operation的依賴關係。 啥叫依賴關係?有啥用啊?打個比方咱們要做一個聽音樂的付費App項目,需要經過登陸、付費、下載、播放四個步驟。其實一看就明白,這四個操作是有先後順序的,但假如所有的操作都是多線程,咱們怎麼控制順序?通過設置“優先順序” ...
  • 上一篇博客描述了一個簡單的串口應用程式和驅動程式,瞭解了應用程式訪問串口的基本操作,如打開串口,設置串口,寫串口,讀串口,關閉串口等。和Linux串口驅動的基本框架。這裡將瞭解Android下的串口系統框架,仍然使用上一篇博客中的tiny_serial.c作為本例的驅動,本例實現的功能不變,無論應用 ...
  • 關註react native這個技術很久了,去年就做了一個簡單的Demo,最近有時間,重新瞭解了一下react native的現狀,發現已經有很大的進步,現在完善了一下原有的項目,並重新開源共用一下。 背景 對react native這個技術關註很久了,去年也花了很長時間學習,但中途因為時間問題沒有 ...
  • DEVELOPER.XIAOYAOLI 技術筆記 簡單的利用UIImagePickerController調用iPhone攝像頭獲取照片的方法,同時介紹了怎麼添加overlay,用於自定義預覽界面 UIImagePickerController是一種獲取攝像頭照片取景器的方法,簡單的實現方法如下,我 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...