非同步編程模型
① 怎樣理解阻塞非阻塞與同步非同步的區別
「阻塞」與"非阻塞"與"同步"與「非同步"不能簡單的從字面理解,提供一個從分布式系統角度的回答。
1.同步與非同步
同步和非同步關注的是消息通信機制 (synchronous communication/ asynchronous communication)
所謂同步,就是在發出一個*調用*時,在沒有得到結果之前,該*調用*就不返回。但是一旦調用返回,就得到返回值了。
換句話說,就是由*調用者*主動等待這個*調用*的結果。
而非同步則是相反,*調用*在發出之後,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個非同步過程調用發出後,調用者不會立刻得到結果。而是在*調用*發出後,*被調用者*通過狀態、通知來通知調用者,或通過回調函數處理這個調用。
典型的非同步編程模型比如Node.js
舉個通俗的例子:
你打電話問書店老闆有沒有《分布式系統》這本書,如果是同步通信機制,書店老闆會說,你稍等,」我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而非同步通信機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這里老闆通過「回電」這種方式來回調。
2. 阻塞與非阻塞
阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態.
阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之後才會返回。
非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。
還是上面的例子,
你打電話問書店老闆有沒有《分布式系統》這本書,你如果是阻塞式調用,你會一直把自己「掛起」,直到得到這本書有沒有的結果,如果是非阻塞式調用,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鍾check一下老闆有沒有返回結果。
在這里阻塞與非阻塞與是否同步非同步無關。跟老闆通過什麼方式回答你結果無關。
② 五體大字系統進階課講什麼
大數據技術在如今應用非常廣泛,許多想入行學習大數據培訓的童鞋不知從何學起,從哪兒開始學首先要根據你的基本情況而定,如果你是零基礎的也不需要擔心,先從基礎開始學起就好了,接下來學習基礎java開始、數據結構、關系型資料庫、linux系統操作,夯實基礎之後,再進入大數據的學習,例如:hadoop離線分析、Storm實時計算、spark內存計算的學習,以道教育大數據課程體系可以如下:
第一階段 WEB 開發基礎
HTML基礎
1、Html基本介紹
2、HTML語法規范
3、基本標簽介紹
4、HTML編輯器/文本文檔/WebStrom/elipse
5、HTML元素和屬性
6、基本的HTML元素
6.1 標題
6.2 段落
6.3 樣式和style屬性
6.3 鏈接 a
6.4 圖像 img
6.5 表格 table
6.6 列表 ul/ol/dl
7、 HTML注釋
8、表單介紹
9、Table標簽
10、DIV布局介紹
11、HTML列表詳解
HTML布局和Bootstrap
1、 HTML塊元素(block)和行內元素(inline)
2、使用div實現網頁布局
3、響應式WEB設計(Responsive Web Design)
4、使用bootstrap實現響應式布局
HTML表單元素
1、HTML表單 form
2、HTML表單元素
3、 HTML input的類型 type
4、 Html input的屬性
CSS基礎
1、CSS簡介及基本語法
2、在HTML文檔中使用CSS
3、CSS樣式
4、CSS選擇器
5、盒子模型
6、布局及定位
CSS高級/CSS3
1、尺寸和對齊
2、分類(clear/cursor/display/float/position/visibility)
3、導航欄
4、圖片庫
5、圖片透明
6、媒介類型 @media
7、CSS3
8、CSS3動畫效果
JavaScript基礎
1、JavaScript簡介
2、基本語法規則
3、在HTML文檔中使用JS
4、JS變數
5、JS數據類型
6、JS函數
7、JS運算符
8、流程式控制制
9、JS錯誤和調試
JavaScript對象和作用域
1、數字 Number
2、字元串String
3、日期 Date
4、數組
5、數學 Math
6、DOM對象和事件
7、BOM對象
8、Window對象
9、作用域和作用域鏈
10、JSON
Javascript庫
1、Jquery
2、Prototype
3、Ext Js
Jquery
1、Jquery基本語法
2、Jquery選擇器
3、Jquery事件
4、Jquery選擇器
5、Jquery效果和動畫
6、使用Jquery操作HTML和DOM
7、Jquery遍歷
8、Jquery封裝函數
9、Jquery案例
表單驗證和Jquery Validate
1、用Js對HTML表單進行驗證
2、Jquery Validata基本用法
3、默認校驗規則和提示信息
4、debug和ignore
5、更改錯誤信息顯示位置和樣式
6、全部校驗通過後的執行函數
7、修改驗證觸發方式
8、非同步驗證
9、自定義校驗方法
10、radio 和 checkbox、select 的驗證
Java基礎
1、關於Java
2、Java運行機制
3、第一個Java程序,注釋
4、Javac,Java,Javadoc等命令
5、標識符與關鍵字
6、變數的聲明,初始化與應用
7、變數的作用域
8、變數重名
9、基本數據類型
10、類型轉換與類型提升
11、各種數據類型使用細節
12、轉義序列
13、各種運算符的使用
流程式控制制
1、選擇控制語句if-else
2、選擇控制語句switch-case
3、循環控制語句while
4、循環控制語句do-while
5、循環控制語句for與增強型for
6、break,continue,return
7、循環標簽
8、數組的聲明與初始化
9、數組內存空間分配
10、棧與堆內存
11、二維(多維)數組
12、Arrays類的相關方法
13、main方法命令行參數
面向對象
1、面向對象的基本思想
2、類與對象
3、成員變數與默認值
4、方法的聲明,調用
5、參數傳遞和內存圖
6、方法重載的概念
7、調用原則與重載的優勢
8、構造器聲明與默認構造器
9、構造器重載
10、this關鍵字的使用
11、this調用構造器原則
12、實例變數初始化方式
13、可變參數方法
訪問許可權控制
1、包 package和庫
2、訪問許可權修飾符private/protected/public/包訪問許可權
3、類的訪問許可權
4、抽象類和抽象方法
5、介面和實現
6、解耦
7、Java的多重繼承
8、通過繼承來擴展介面
錯誤和異常處理
1、概念:錯誤和異常
2、基本異常
3、捕獲異常 catch
4、創建自定義異常
5、捕獲所有異常
6、Java標准異常
7、使用finally進行清理
8、異常的限制
9、構造器
10、異常匹配
11、異常使用指南
資料庫基礎(Mysql)
資料庫基礎(MySQL)
JDBC
1、Jdbc基本概念
2、使用Jdbc連接資料庫
3、使用Jdbc進行crud操作
4、使用Jdbc進行多表操作
5、Jdbc驅動類型
6、Jdbc異常和批量處理
7、Jdbc儲存過程
Servlet和JSP
1、Servlet簡介
2、Request對象
3、Response對象
4、轉發和重定向
5、使用Servlet完成Crud
6、Session和Coolie簡介
7、ServletContext和Jsp
8、El和Jstl的使用
Ajax
1、什麼是Ajax
2、XMLHttpRequest對象(XHR)
3、XHR請求
4、XHR響應
5、readystate/onreadystatechange
6、Jquery Ajax
7、JSON
8、案例:對用戶名是否可用進行伺服器端校驗
綜合案例
1、項目開發一般流程介紹
2、模塊化和分層
3、DButils
4、QueryRunner
5、ResultSetHandle
6、案例:用戶登錄/注冊,從前端到後端
第二階段 Java SE
訪問許可權和繼承
1、包的聲明與使用
2、import與import static
3、訪問許可權修飾符
4、類的封裝性
5、static(靜態成員變數)
6、final(修飾變數,方法)
7、靜態成員變數初始化方式
8、類的繼承與成員繼承
9、super的使用
10、調用父類構造器
11、方法的重寫與變數隱藏
12、繼承實現多態和類型轉換
13、instanceof
抽象類與介面
1、抽象類
2、抽象方法
3、繼承抽象類
4、抽象類與多態
5、介面的成員
6、靜態方法與默認方法
7、靜態成員類
8、實例成員類
9、局部類
10、匿名類
11、eclipse的使用與調試
12、內部類對外圍類的訪問關系
13、內部類的命名
Lambda表達式與常用類
1、函數式介面
2、Lambda表達式概念
3、Lambda表達式應用場合
4、使用案例
5、方法引用
6、枚舉類型(編譯器的處理)
7、包裝類型(自動拆箱與封箱)
8、String方法
9、常量池機制
10、String講解
11、StringBuilder講解
12、Math,Date使用
13、Calendars使用
異常處理與泛型
1、異常分類
2、try-catch-finally
3、try-with-resources
4、多重捕獲multi-catch
5、throw與throws
6、自定義異常和優勢
7、泛型背景與優勢
8、參數化類型與原生類型
9、類型推斷
10、參數化類型與數組的差異
11、類型通配符
12、自定義泛型類和類型擦出
13、泛型方法重載與重寫
集合
1 、常用數據結構
2 、Collection介面
3 、List與Set介面
4 、SortedSet與NavigableSet
5 、相關介面的實現類
6 、Comparable與Comparator
7、Queue介面
8 、Deque介面
9 、Map介面
10、NavigableMap
11、相關介面的實現類
12、流操作(聚合操作)
13、Collections類的使用
I/O流與反射
1 、File類的使用
2 、位元組流
3 、字元流
4 、緩存流
5 、轉換流
6 、數據流
7、對象流
8、類載入,鏈接與初始化
9 、ClassLoader的使用
10、Class類的使用
11、通過反射調用構造器
12、安全管理器
網路編程模型與多線程
1、進程與線程
2、創建線程的方式
3、線程的相關方法
4、線程同步
5、線程死鎖
6、線程協作操作
7、計算機網路(IP與埠)
8、TCP協議與UDP協議
9、URL的相關方法
10、訪問網路資源
11、TCP協議通訊
12、UDP協議通訊
13、廣播
SSM-Spring
1.Spring/Spring MVC
2.創建Spring MVC項目
3.Spring MVC執行流程和參數
SSM-Spring.IOC
1.Spring/Spring MVC
2.創建Spring MVC項目
3.Spring MVC執行流程和參數
SSM-Spring.AOP
1.Spring/Spring MVC
2.創建Spring MVC項目
3.Spring MVC執行流程和參數
SSM-Spring.Mybatis
1.MyBatis簡介
2.MyBatis配置文件
3.用MyBatis完成CRUD
4.ResultMap的使用
5.MyBatis關聯查詢
6.動態SQL
7.MyBatis緩沖
8.MyBatis-Generator
Socket編程
1.網路通信和協議
2.關於Socket
3.Java Socket
4.Socket類型
5.Socket函數
6.WebSocket
7.WebSocket/Spring MVC/WebSocket Ajax
IO/非同步
window對象
全局作用域
窗口關系及框架
窗口位置和大小
打開窗口
間歇調用和超時調用(靈活運用)
系統對話框
location對象
navigator對象
screen對象
history對象
NIO/AIO
1.網路編程模型
2.BIO/NIO/AIO
3.同步阻塞
4.同步非阻塞
5.非同步阻塞
6.非同步非阻塞
7.NIO與AIO基本操作
8.高性能IO設計模式
第三階段 Java 主流框架
MyBatis
1.mybatis框架原理分析
2.mybatis框架入門程序編寫
3.mybatis和hibernate的本質區別和應用場景
4.mybatis開發方法
5.SqlMapConfig配置文件講解
6.輸入映射-pojo包裝類型的定義與實現
7.輸出映射-resultType、resultMap
8.動態sql
9.訂單商品數據模型分析
10.高級映射的使用
11.查詢緩存之一級緩存、二級緩存
12.mybatis與spring整合
13. mybatis逆向工程自動生成代碼
Spring/Spring MVC
1. springmvc架構介紹
2. springmvc入門程序
3. spring與mybatis整合
4. springmvc註解開發—商品修改功能分析
5. springmvc註解開發—RequestMapping註解
6. springmvc註解開發—Controller方法返回值
7. springmvc註解開發—springmvc參數綁定過程分析
8. springmvc註解開發—springmvc參數綁定實例講解
9. springmvc與struts2的區別
10. springmvc異常處理
11. springmvc上傳圖片
12. springmvc實現json交互
13. springmvc對RESTful支持
14. springmvc攔截器
第四階段 關系型資料庫/MySQL/NoSQL
SQL基礎
1.SQL及主流產品
2.MySQL的下載與安裝(sinux/windows)
3.MySql的基本配置/配置文件
4.基本的SQL操作 DDL
5.基本的SQL操作 DML
6.基本的SQL操作 DCL
7.MySQL客戶端工具
8.MySQL幫助文檔
MySQL數據類型和運算符
1 數值類型
2 日期時間類型
3 字元串類型
4 CHAR 和 VARCHAR 類型
5 BINARY 和 VARBINARY 類型
6 ENUM 類型
7 SET 類型
8 算術運算符
9 比較運算符
10 邏輯運算符
11 位運算
12 運算符的優先順序
MySQL函數
1 字元串函數
2 數值函數
3 日期和時間函數
4 流程函數
5 其他常用函數
MySQL存儲引擎
1.MySQL支持的存儲引擎及其特性
2.MyISAM
3.InnoDB
4.選擇合適的存儲引擎
選擇合適的數據類型
1 CHAR 與 VARCHAR
2 TEXT 與 BLOB
3 浮點數與定點數
4 日期類型選擇
字元集
1 字元集概述
2 Unicode字元集
3 漢字及一些常見字元集
4 選擇合適的字元集
5 MySQL 支持的字元集
6 MySQL 字元集的設置 .
索引的設計和使用
1.什麼是索引
2.索引的類型
3.索引的數據結構 BTree B+Tree Hash
4.索引的存儲
5.MySQL索引
6.查看索引的使用情況
7.索引設計原則
視圖/存儲過程/函數/觸發器
1. 什麼是視圖
2. 視圖操作
3. 什麼是存儲過程
4. 存儲過程操作
5. 什麼是函數
6. 函數的相關操作
7. 觸發器
事務控制/鎖
1. 什麼是事務
2. 事務控制
3. 分布式事務
4. 鎖/表鎖/行鎖
5. InnoDB 行鎖爭用
6. InnoDB 的行鎖模式及加鎖方法7
7 InnoDB 行鎖實現方式7
8 間隙鎖(Next-Key 鎖)
9 恢復和復制的需要,對 InnoDB 鎖機制的影響
10 InnoDB 在不同隔離級別下的一致性讀及鎖的差異
11 表鎖
12 死鎖
SQL Mode和安全問題
1. 關於SQL Mode
2. MySQL中的SQL Mode
3. SQL Mode和遷移
4. SQL 注入
5. 開發過程中如何避免SQL注入
SQL優化
1.通過 show status 命令了解各種 SQL 的執行頻率
2. 定位執行效率較低的 SQL 語句
3. 通過 EXPLAIN 分析低效 SQL 的執行計劃
4. 確定問題並採取相應的優化措施
5. 索引問題
6.定期分析表和檢查表
7.定期優化表
8.常用 SQL 的優化
MySQL資料庫對象優化
1. 優化表的數據類型
2 散列化
3 逆規范化
4 使用中間表提高統計查詢速度
5. 影響MySQL性能的重要參數
6. 磁碟I/O對MySQL性能的影響
7. 使用連接池
8. 減少MySQL連接次數
9. MySQL負載均衡
MySQL集群
MySQL管理和維護
MemCache
Redis
在Java項目中使用MemCache和Redis
第五階段:操作系統/Linux、雲架構
Linux安裝與配置
1、安裝Linux至硬碟
2、獲取信息和搜索應用程序
3、進階:修復受損的Grub
4、關於超級用戶root
5、依賴發行版本的系統管理工具
6、關於硬體驅動程序
7、進階:配置Grub
系統管理與目錄管理
1、Shell基本命令
2、使用命令行補全和通配符
3、find命令、locate命令
4、查找特定程序:whereis
5、Linux文件系統的架構
6、移動、復制和刪除
7、文件和目錄的許可權
8、文件類型與輸入輸出
9、vmware介紹與安裝使用
10、網路管理、分區掛載
用戶與用戶組管理
1、軟體包管理
2、磁碟管理
3、高級硬碟管理RAID和LVM
4、進階:備份你的工作和系統
5、用戶與用戶組基礎
6、管理、查看、切換用戶
7、/etc/...文件
8、進程管理
9、linux VI編輯器,awk,cut,grep,sed,find,unique等
Shell編程
1、 SHELL變數
2、傳遞參數
3、數組與運算符
4、SHELL的各類命令
5、SHELL流程式控制制
6、SHELL函數
7、SHELL輸入/輸出重定向
8、SHELL文件包含
伺服器配置
1、系統引導
2、管理守護進程
3、通過xinetd啟動SSH服務
4、配置inetd
5、Tomcat安裝與配置
6、MySql安裝與配置
7、部署項目到Linux
第六階段:Hadoop生態系統
Hadoop基礎
1、大數據概論
2、 Google與Hadoop模塊
3、Hadoop生態系統
4、Hadoop常用項目介紹
5、Hadoop環境安裝配置
6、Hadoop安裝模式
7、Hadoop配置文件
HDFS分布式文件系統
1、認識HDFS及其HDFS架構
2、Hadoop的RPC機制
3、HDFS的HA機制
4、HDFS的Federation機制
5、 Hadoop文件系統的訪問
6、JavaAPI介面與維護HDFS
7、HDFS許可權管理
8、hadoop偽分布式
Hadoop文件I/O詳解
1、Hadoop文件的數據結構
2、 HDFS數據完整性
3、文件序列化
4、Hadoop的Writable類型
5、Hadoop支持的壓縮格式
6、Hadoop中編碼器和解碼器
7、 gzip、LZO和Snappy比較
8、HDFS使用shell+Java API
MapRece工作原理
1、MapRece函數式編程概念
2、 MapRece框架結構
3、MapRece運行原理
4、Shuffle階段和Sort階段
5、任務的執行與作業調度器
6、自定義Hadoop調度器
7、 非同步編程模型
8、YARN架構及其工作流程
MapRece編程
1、WordCount案例分析
2、輸入格式與輸出格式
3、壓縮格式與MapRece優化
4、輔助類與Streaming介面
5、MapRece二次排序
6、MapRece中的Join演算法
7、從MySQL讀寫數據
8、Hadoop系統調優
Hive數據倉庫工具
1、Hive工作原理、類型及特點
2、Hive架構及其文件格式
3、Hive操作及Hive復合類型
4、Hive的JOIN詳解
5、Hive優化策略
6、Hive內置操作符與函數
7、Hive用戶自定義函數介面
8、Hive的許可權控制
Hive深入解讀
1 、安裝部署Sqoop
2、Sqoop數據遷移
3、Sqoop使用案例
4、深入了解資料庫導入
5、導出與事務
6、導出與SequenceFile
7、Azkaban執行工作流
Sqoop與Oozie
1 、安裝部署Sqoop
2、Sqoop數據遷移
3、Sqoop使用案例
4、深入了解資料庫導入
5、導出與事務
6、導出與SequenceFile
7、Azkaban執行工作流
Zookeeper詳解
1、Zookeeper簡介
2、Zookeeper的下載和部署
3、Zookeeper的配置與運行
4、Zookeeper的本地模式實例
5、Zookeeper的數據模型
6、Zookeeper命令行操作範例
7、storm在Zookeeper目錄結構
NoSQL、HBase
1、HBase的特點
2、HBase訪問介面
3、HBase存儲結構與格式
4、HBase設計
5、關鍵演算法和流程
6、HBase安裝
7、HBase的SHELL操作
8、HBase集群搭建
第七階段:Spark生態系統
Spark
1.什麼是Spark
2.Spark大數據處理框架
3.Spark的特點與應用場景
4.Spark SQL原理和實踐
5.Spark Streaming原理和實踐
6.GraphX SparkR入門
7.Spark的監控和調優
Spark部署和運行
1.WordCount准備開發環境
2.MapRece編程介面體系結構
3.MapRece通信協議
4.導入Hadoop的JAR文件
5.MapRece代碼的實現
6.打包、部署和運行
7.打包成JAR文件
Spark程序開發
1、啟動Spark Shell
2、載入text文件
3、RDD操作及其應用
4、RDD緩存
5、構建Eclipse開發環境
6、構建IntelliJ IDEA開發環境
7、創建SparkContext對象
8、編寫編譯並提交應用程序
Spark編程模型
1、RDD特徵與依賴
2、集合(數組)創建RDD
3、存儲創建RDD
4、RDD轉換 執行 控制操作
5、廣播變數
6、累加器
作業執行解析
1、Spark組件
2、RDD視圖與DAG圖
3、基於Standalone模式的Spark架構
4、基於YARN模式的Spark架構
5、作業事件流和調度分析
6、構建應用程序運行時環境
7、應用程序轉換成DAG
Spark SQL與DataFrame
1、Spark SQL架構特性
2、DataFrame和RDD的區別
3、創建操作DataFrame
4、RDD轉化為DataFrame
5、載入保存操作與Hive表
6、Parquet文件JSON數據集
7、分布式的SQL Engine
8、性能調優 數據類型
深入Spark Streaming
1、Spark Streaming工作原理
2、DStream編程模型
3、Input DStream
4、DStream轉換 狀態 輸出
5、優化運行時間及內存使用
6、文件輸入源
7、基於Receiver的輸入源
8、輸出操作
Spark MLlib與機器學習
1、機器學習分類級演算法
2、Spark MLlib庫
3、MLlib數據類型
4、MLlib的演算法庫與實例
5、ML庫主要概念
6、演算法庫與實例
GraphX與SparkR
1、Spark GraphX架構
2、GraphX編程與常用圖演算法
3、GraphX應用場景
4、SparkR的工作原理
5、R語言與其他語言的通信
6、SparkR的運行與應用
7、R的DataFrame操作方法
8、SparkR的DataFrame
Scala編程開發
1、Scala語法基礎
2、idea工具安裝
3、maven工具配置
4、條件結構、循環、高級for循環
5、數組、映射、元組
6、類、樣例類、對象、伴生對象
7、高階函數與函數式編程
Scala進階
1、 柯里化、閉包
2、模式匹配、偏函數
3、類型參數
4、協變與逆變
5、隱式轉換、隱式參數、隱式值
6、Actor機制
7、高級項目案例
Python編程
1、Python編程介紹
2、Python的基本語法
3、Python開發環境搭建
4、Pyhton開發Spark應用程序
第八階段:Storm生態系統
storm簡介與基本知識
1、storm的誕生誕生與成長
2、storm的優勢與應用
3、storm基本知識概念和配置
4、序列化與容錯機制
5、可靠性機制—保證消息處理
6、storm開發環境與生產環境
7、storm拓撲的並行度
8、storm命令行客戶端
Storm拓撲與組件詳解
1、流分組和拓撲運行
2、拓撲的常見模式
3、本地模式與stormsub的對比
4、 使用非jvm語言操作storm
5、hook、組件基本介面
6、基本抽象類
7、事務介面
8、組件之間的相互關系
spout詳解 與bolt詳解
1、spout獲取數據的方式
2、常用的spout
3、學習編寫spout類
4、bolt概述
5、可靠的與不可靠的bolt
6、復合流與復合anchoring
7、 使用其他語言定義bolt
8、學習編寫bolt類
storm安裝與集群搭建
1、storm集群安裝步驟與准備
2、本地模式storm配置命令
3、配置hosts文件、安裝jdk
4、zookeeper集群的搭建
5、部署節點
6、storm集群的搭建
7、zookeeper應用案例
8、Hadoop高可用集群搭建
Kafka
1、Kafka介紹和安裝
2、整合Flume
3、Kafka API
4、Kafka底層實現原理
5、Kafka的消息處理機制
6、數據傳輸的事務定義
7、Kafka的存儲策略
Flume
1、Flume介紹和安裝
2、Flume Source講解
3、Flume Channel講解
4、Flume Sink講解
5、flume部署種類、流配置
6、單一代理、多代理說明
7、flume selector相關配置
Redis
1、Redis介紹和安裝、配置
2、Redis數據類型
3、Redis鍵、字元串、哈希
4、Redis列表與集合
5、Redis事務和腳本
6、Redis數據備份與恢復
7、Redis的SHELL操作
③ jQuery鏈式操作如何實現以及為什麼要用鏈式操作
鏈式操作
原理相信網路一下一大把,實際上鏈式操作僅僅是通過對象上的方法最後
return this
把對象再返回回來,對象當然可以繼續調用方法啦,所以就可以鏈式操作了。那麼,簡單實現一個:
復制代碼 代碼如下:
//定義一個JS類
function Demo() {
}
//擴展它的prototype
Demo.prototype ={
setName:function (name) {
this.name = name;
return this;
},
getName:function () {
return this.name;
},
setAge:function (age) {
this.age = age;
return this;
}
};
////工廠函數
function D() {
return new Demo();
}
//去實現可鏈式的調用
D().setName("CJ").setAge(18).setName();
但……為什麼要用呢?
一般的解釋:
節省代碼量,代碼看起來更優雅。
例如如果沒有鏈式,那麼你可能需要這樣寫代碼:
復制代碼 代碼如下:
document.getElementById("ele").dosomething();
document.getElementById("ele").dootherthing();
這個代碼中調用了兩次document.getElementById來獲取DOM樹的元素,這樣消耗比較大,而且要寫兩行,而鏈式只要寫一行,節省了代碼……
但我們也可以用緩存元素啊。比如:
復制代碼 代碼如下:
var ele = document.getElementById("ele");
ele.dosomething();
ele.dootherthing();
而且兩行並沒有比一行多多少代碼,甚至相應的封裝反而使得代碼更多了。
最糟糕的是所有對象的方法返回的都是對象本身,也就是說沒有返回值,這不一定在任何環境下都適合。
舉個例子,我們想弄一個超大整數BigInteger(意思是如果用Javascript的Number保存可能會溢出的整數),順便擴展他的運算方法,會適合用鏈式操作么?
例如運算31415926535 * 4 - 271828182,如果設計成鏈式風格的方法可能會是這樣的:
復制代碼 代碼如下:
var result = (new BigInteger("31415926535")).multiply(new BigInteger("4")).subtract(new BigInteger("271828182")).val();
console.log("result == " + result);
這看起來似乎也很優雅,但是如果我們想要中間的結果怎麼辦呢?或許會寫成這樣:
復制代碼 代碼如下:
var bigInteger = new BigInteger("31415926535");
var result1 = bigInteger.multiply(new BigInteger("4")).val();
var result2 = bigInteger.subtract(new BigInteger("271828182")).val();
console.log("result1 == " + result1 + ", result2 == " + result2);
這似乎一點也不優雅了,和不用鏈式操作沒啥不同嘛!
那麼如果要求是原來的BigInteger不能改變呢?好吧,鏈式操作似乎不能滿足這個需求了。
那麼到底為什麼要用鏈式操作呢?
為了更好的非同步體驗
Javascript是無阻塞語言,所以他不是沒阻塞,而是不能阻塞,所以他需要通過事件來驅動,非同步來完成一些本需要阻塞進程的操作。
但是非同步編程是一種令人瘋狂的東西……運行時候是分離的倒不要緊,但是編寫代碼時候也是分離的就……
常見的非同步編程模型有哪些呢?
•回調函數
所謂的回調函數,意指先在系統的某個地方對函數進行注冊,讓系統知道這個函數的存在,然後在以後,當某個事件發生時,再調用這個函數對事件進行響應。
復制代碼 代碼如下:
function f(num, callback){
if(num<0) {
alert("調用低層函數處理!");
alert("分數不能為負,輸入錯誤!");
}else if(num==0){
alert("調用低層函數處理!");
alert("該學生可能未參加考試!");
}else{
alert("調用高層函數處理!");
setTimeout(function(){callback();}, 1000);
}
}
這里callback則是回調函數。可以發現只有當num為非負數時候callback才會調用。
但是問題,如果我們不看函數內部,我們並不知道callback會幾時調用,在什麼情況下調用,代碼間產生了一定耦合,流程上也會產生一定的混亂。
雖然回調函數是一種簡單而易於部署的實現非同步的方法,但從編程體驗來說它卻不夠好。
•事件監聽
也就是採用事件驅動,執行順序取決於事件順序。
復制代碼 代碼如下:
function EventTarget(){
this.handlers = {};
}
EventTarget.prototype = {
constructor: EventTarget,
addHandler: function(type, handler){
this.handlers[type] = [];
},
fire: function(){
if(!event.target){
event.target = this;
}
if(this.handlers[event.type instanceof Array]){
var handlers = this.handlers[event.type];
for(var i = 0, len = handlers.length, i < len; i++){
handlers[i](event);
}
}
},
removeHandler: function(type, handler){
if(this.handlers[type] instanceof Array){
var handlers = this.handlers[type];
for(var i = 0, le = handlers.length; i < len; i++){
if(handlers[i] === handler){
break;
}
}
handlers.splice(i, 1);
}
}
};
上面是《JavaScript高級程序設計》中的自定義事件實現。於是我們就可以通過addHandler來綁定事件處理函數,用fire來觸發事件,用removeHandler來刪除事件處理函數。
雖然通過事件解耦了,但流程順序更加混亂了。
•鏈式非同步
個人覺得鏈式操作最值得稱贊的還是其解決了非同步編程模型的執行流程不清晰的問題。jQuery中$(document).ready就非常好的闡釋了這一理念。DOMCotentLoaded是一個事件,在DOM並未載入前,jQuery的大部分操作都不會奏效,但jQuery的設計者並沒有把他當成事件一樣來處理,而是轉成一種「選其對象,對其操作」的思路。$選擇了document對象,ready是其方法進行操作。這樣子流程問題就非常清晰了,在鏈條越後位置的方法就越後執行。
復制代碼 代碼如下:
(function(){
var isReady=false; //判斷onDOMReady方法是否已經被執行過
var readyList= [];//把需要執行的方法先暫存在這個數組里
var timer;//定時器句柄
ready=function(fn) {
if (isReady )
fn.call( document);
else
readyList.push( function() { return fn.call(this);});
return this;
}
var onDOMReady=function(){
for(var i=0;i<readyList.length;i++){
readyList[i].apply(document);
}
readyList = null;
}
var bindReady = function(evt){
if(isReady) return;
isReady=true;
onDOMReady.call(window);
if(document.removeEventListener){
document.removeEventListener("DOMContentLoaded", bindReady, false);
}else if(document.attachEvent){
document.detachEvent("onreadystatechange", bindReady);
if(window == window.top){
clearInterval(timer);
timer = null;
}
}
};
if(document.addEventListener){
document.addEventListener("DOMContentLoaded", bindReady, false);
}else if(document.attachEvent){
document.attachEvent("onreadystatechange", function(){
if((/loaded|complete/).test(document.readyState))
bindReady();
});
if(window == window.top){
timer = setInterval(function(){
try{
isReady||document.documentElement.doScroll('left');//在IE下用能否執行doScroll判斷dom是否載入完畢
}catch(e){
return;
}
bindReady();
},5);
}
}
})();
上面的代碼不能用$(document).ready,而應該是window.ready。
•Promise
CommonJS中的非同步編程模型也延續了這一想法,每一個非同步任務返回一個Promise對象,該對象有一個then方法,允許指定回調函數。
所以我們可以這樣寫:
f1().then(f2).then(f3);
這種方法我們無需太過關注實現,也不太需要理解非同步,只要懂得通過函數選對象,通過then進行操作,就能進行非同步編程。
④ 淺談Node.js非同步編程中回調和非同步調用的區別
非同步編程模型是Node.js的主要特色,node.js的很多第三方模塊都提供了非同步的API。本文著重闡述了同步調用、非同步調用及回調與非同步調用的區別,通過案例說明回調函數的用法
⑤ javascript動畫為什麼是非同步操作
JavaScript中的非同步梳理(2)——使用Promises/A
Promises是一種非同步編程模型,通過一組API來規范化非同步操作,這樣也能夠讓非同步操作的流程式控制制更加容易。
這里談的是Promises/A,算是Promises的一個分支吧,其實就是根據Promises模型定義了一組API。由於Promises對於新手而言理解曲線還是比較陡峭的,這里循序漸進的給大家介紹,同時實現一個最簡單的Promises/A代碼。
Promises/A有個別名叫做「thenable」,就是「可以then」的。這里一個promise有三種狀態:[默認、完成、失敗],初始創建的時候是默認狀態,狀態只可以從默認變成完成,或者默認變成失敗。一旦完成或者失敗,狀態就不能再變。為了簡化文章,這里我們先只考慮完成,不考慮失敗。
var Promise = function(ok){
this.state = 'unfulfilled';
this.ok = || function(obj) { return obj; };
};
Promise.prototype = {
resolve: function(obj){
if (this.state !== 'unfulfilled') throw '已完成,不能再次resolve';
this.state = 'fulfilled';
}
};
var promise = new Promise(function(obj){ return obj; });
構造函數中的ok是一個任務,promise.resolve(obj)表示將該promise的狀態改為完成,此時ok會被執行,其返回值作為後續操作的參數以及resolve的返回值。
由於沒有和任何非同步操作關聯在一起,這里的Promise還沒有任何作用。
Promises/A之所以叫「thenable」是因為它的核心API叫做then,望文生義這個方法的作用是當一個promise完成或失敗後繼續干別的事情。
then傳入一個函數作為參數nextOK①,當該promise被resolve時,resolve的返回值將會傳遞到nextOK中。
then返回一個promise,當上述後續操作完成時,返回的promise也會被resolve。
如果promise的狀態是已完成,則nextOK會被立即調用。
但是這樣並無法非同步,因此這里有一個特殊情況,就是如果nextOK的返回值也是一個Promise,那麼then返回的promise需要當這個promise被resolve時才會被resolve。
var Promise = function(ok){
this.state = 'unfulfilled';
this.ok = ok || function(obj) { return obj; };
this.thens = [];
};
Promise.prototype = {
resolve: function(obj){
if (this.state != 'unfulfilled') throw '已完成,不能再次resolve';
this.state = 'fulfilled';
this.result = this.ok(obj); // 執行ok
for (var i=0, len=this.thens.length; i<len; ++i){
// 依次調用該任務的後續任務
var then = this.thens[i];
this._fire(then.promise, then.ok);
}
return this;
},
_fire: function(nextPromise, nextOK){
var nextResult = nextOK(this.result); // 調用nextOK
if (nextResult instanceof Promise){
// 非同步的情況,返回值是一個Promise,則當其resolve的時候,nextPromise才會被resolve
nextResult.then(function(obj){
nextPromise.resolve(obj);
});
}else{
// 同步的情況,返回值是普通結果,立即將nextPromise給resolve掉
nextPromise.resolve(nextResult);
}
return nextPromise;
},
_push: function(nextPromise, nextOK){
this.thens.push({
promise: nextPromise,
ok: nextOK
});
return nextPromise;
},
then: function(nextOK){
var promise = new Promise();
if (this.state == 'fulfilled'){
// 如果當前狀態是已完成,則nextOK會被立即調用
return this._fire(promise, nextOK);
}else{
// 否則將會被加入隊列中
return this._push(promise, nextOK);
}
}
};
到到了這里,我們的極簡版Promise就完成了,那麼如何使用呢?
這里舉個例子,首先定義一些「任務」,例如:
function print(num){
console.log(num);
return num;
}
function addTwo(num){
return num + 2;
}
按需要組織這些任務
var promise = new Promise(print);
promise.then(addTwo)
.then(print)
.then(addTwo)
.then(print); // 這里的任務將會加入到隊列中
promise.resolve(3); // 激活整個隊列
可以看到控制台里依次列印出了3、5和7。
但這些任務都是同步的,無法體現出Promise的強大之處——非同步控制。這里我們通過nextOK返回promise的方法來實現一個delay。
function delay(ms){
return function(obj){
var promise = new Promise();
setTimeout(function(){
promise.resolve(obj);
}, ms);
return promise;
};
}
利用它來改造上面的任務隊列,讓後兩次列印之間延遲2秒:
var promise = new Promise(print);
promise.then(addTwo)
.then(print)
.then(delay(2000)) // 延遲2秒
.then(addTwo)
.then(print);
promise.resolve(3);
利用這個原理,可以做一些巧妙的代碼:
function fibNext(pair){
print(pair[0]);
return [pair[1], pair[0]+pair[1]];
}
var promise = new Promise(fibNext);
promise.then(function(pair){
promise = promise.then(delay(1000))
.then(fibNext)
.then(arguments.callee);
return pair;
});
promise.resolve([1,1]);
上面沒有使用循環,但是實現了一個無限每隔1秒自動列印的斐波那契數列。
Promises模型相當優雅,通過一些擴展可以實現諸如when, whenAll等API,對於封裝非同步操作非常有幫助。
事實上的庫中不常直接用Promise這個名字,而常用Deferred,Defer的意思是「延遲」,因此Deferred常被成為「延遲隊列」或者「非同步隊列」。在jQuery 1.5中引入了jQuery.Deferred,Dojo在這方面也是先行者,dojo 0.3就實現了Deferred。事實上在使用了Deferred之後,jQuery.ajax和dojo.ajax返回的結果都是Deferred,因此可以用then取代傳統的傳入回調函數的形式,非常方便,例如在dojo中可以:
dojo.xhrGet({
url: "users.json",
handleAs: "json"
}).then(function(userList){
dojo.forEach(userList, function(user){
appendUser(user);
});
});
使用這樣的代碼可以隨時對ajax請求添加回調,而不一定是在定義之初設定回調,靈活性更強。
⑥ 全面解析C#中的非同步編程
當我們處理一些長線的調用時,經常會導致界面停止響應或者IIS線程佔用過多等問題,這個時候我們需要更多的是用非同步編程來修正這些問題,但是通常都是說起來容易做起來難,誠然非同步編程相對於同步編程來說,它是一種完全不同的編程思想,對於習慣了同步編程的開發者來說,在開發過程中難度更大,可控性不強是它的特點。
在.NET
Framework5.0種,微軟為我們系統了新的語言特性,讓我們使用非同步編程就像使用同步編程一樣相近和簡單,本文中將會解釋以前版本的Framework中基於回調道德非同步編程模型的一些限制以及新型的API如果讓我們簡單的做到同樣的開發任務。
為什麼要非同步
一直以來,使用遠程資源的編程都是一個容易造成困惑的問題,不同於“本地資源”,遠程資源的訪問總會有很多意外的情況,網路環境的不穩定機器服務端的故障,會造成很多程序員完全不可控的問題,所以這也就要求程序員需要更多的去保護遠程資源的調用,管理調用的取消、超市、線程的等待以及處理線程長時間沒響應的情況等。而在.NET中我們通常忽略了這些挑戰,事實上我們會有多種不用的模式來處理非同步編程,比如在處理IO密集型操作或者高延遲的操作時候不組測線程,多數情況我們擁有同步和非同步兩個方法來做這件事。可是問題在於當前的這些模式非常容易引起混亂和代碼錯誤,或者開發人員會放棄然後使用阻塞的方式去開發。
而在如今的.NET中,提供了非常接近於同步編程的編程體驗,不需要開發人員再去處理只會在非同步編程中出現的很多情況,非同步調用將會是清晰的且不透明的,而且易於和同步的代碼進行組合使用。
過去糟糕的體驗
最好的理解這種問題的方式是我們最常見的一種情況:用戶界面只擁有一個線程所有的工作都運行在這個線程上,客戶端程序不能對用戶的滑鼠時間做出反應,這很可能是因為應用程序正在被一個耗時的操作所阻塞,這可能是因為線程在等待一個網路ID或者在做一個CPU密集型的計算,此時用戶界面不能獲得運行時間,程序一直處於繁忙的狀態,這是一個非常差的用戶體驗。
很多年來,解決這種問題的方法都是做非同步花的調用,不要等待響應,盡快的返回請求,讓其他事件可以同時執行,只是當請求有了最終反饋的時候通知應用程序讓客戶代碼可以執行指定的代碼。
而問題在於:非同步代碼完全毀掉了代碼流程,回調代理解釋了之後如何工作,但是怎麼在一個while循環里等待?一個if語句?一個try塊或者一個using塊?怎麼去解釋“接下來做什麼”?
看下面的一個例子:
public
int
SumPageSizes(IList
uris)
{
int
total
=
0;
foreach
(var
uri
in
uris)
{
txtStatus.Text
=
string.Format("Found
{0}
bytes...",
total);
var
data
=
new
WebClient().DownloadData(uri);
total
+=
data.Length;
}
txtStatus.Text
=
string.Format("Found
{0}
bytes
total",
total);
return
total;
}
這個方法從一個uri列表裡下載文件,統計他們的大小並且同時更新狀態信息,很明顯這個方法不屬於UI線程因為它需要花費非常長的時間來完成,這樣它會完全的掛起UI,但是我們又希望UI能被持續的更新,怎麼做呢?
我們可以創建一個後台編程,讓它持續的給UI線程發送數據來讓UI來更新自身,這個看起來是很浪費的,因為這個線程把大多時間花在等下和下載上,但是有的時候,這正是我們需要做的。在這個例子中,WebClient提供了一個非同步版本的DownloadData方法—DownloadDataAsync,它會立即返回,然後在DownloadDataCompleted後觸發一個事件,這允許用戶寫一個非同步版本的方法分割所要做的事,調用立即返回並完成接下來的UI線程上的調用,從而不再阻塞UI線程。下面是第一次嘗試:
public
void
SumpageSizesAsync(IList
uris)
{
SumPageSizesAsyncHelper(uris.GetEnumerator(),
0);
}
public
void
SumPageSizesAsyncHelper(IEnumerator
enumerator,
int
total)
{
if
(enumerator.MoveNext())
{
txtStatus.Text
=
string.Format("Found
{0}
bytes...",
total);
var
client
=
new
WebClient();
client.DownloadDataCompleted
+=
(sender,e)=>{
SumPageSizesAsyncHelper(enumerator,
total
+
e.Result.Length);
};
client.DownloadDataAsync(enumerator.Current);
}
else
{
txtStatus.Text
=
string.Format("Found
{0}
bytes
total",
total);
}
}
然後這依然是糟糕的,我們破壞了一個整潔的foreach循環並且手動獲得了一個enumerator,每一個調用都創建了一個事件回調。代碼用遞歸取代了循環,這種代碼你應該都不敢直視了吧。不要著急,還沒有完
。
原始的代碼返回了一個總數並且顯示它,新的一步版本在統計還沒有完成之前返回給調用者。我們怎麼樣才可以得到一個結果返回給調用者,答案是:調用者必須支持一個回掉,我們可以在統計完成之後調用它。
然而異常怎麼辦?原始的代碼並沒有關注異常,它會一直傳遞給調用者,在非同步版本中,我們必須擴展回掉來讓異常來傳播,在異常發生時,我們不得不明確的讓它傳播。
⑦ C#幾種非同步編程
1、非同步編程模型 (APM) 模式(也稱為 IAsyncResult 模式),其中非同步操作要求 Begin 和 End 方法(例如,非同步寫操作的 BeginWrite 和 EndWrite)。對於新的開發工作不再建議採用此模式。
2、基於事件的非同步模式 (EAP) 需要一個具有 Async 後綴的方法,還需要一個或多個事件、事件處理程序、委託類型和 EventArg 派生的類型。EAP 是在 .NET Framework 2.0 版中引入的。對於新的開發工作不再建議採用此模式。
3、基於任務的非同步模式 (TAP),該模式使用一個方法表示非同步操作的啟動和完成。.NET Framework 4 中引入了 TAP,並且是 .NET Framework 中非同步編程的建議方
⑧ C#中udp非同步編程之煩惱
這個非同步編程模型基本上就是掌握Begin函數和End函數就好了。
首先調用Begin,送一個委託(其實就是你自己寫的一個函數)進去當參數,其他幾個參數和同步的沒什麼太大區別。好了就沒你什麼事了……同步的時候此時是在等對吧,非同步的就沒得等了,函數直接返回。同步的時候函數返回就可以開始處理數據了對吧?非同步的時候要等你送進去當參數的那個函數被調用的時候才能開始處理數據。
等到數據來了或者異常發生了,它會調用你那個函數,把IAsyncResult介面的某個對象當作參數送進來。此時你調用End那個函數,就可以拿到結果了(如果接收過程中有異常發生,End函數會拋出那個異常)
⑨ C#利用socekt做到http監聽,怎麼樣才能做到高性能
用非同步Socket編程去替代同步Socket編程是優化Socket的IO性能的一個途徑,因為非同步IO不會阻塞線程,在請求量大的時候體現出更佳的性能。
C#提供了3中不同的非同步編程模式:
1、非同步編程模型 (APM) 模式,其方法通常以Begin和End成對出現,已經不推薦使用。
2、基於事件的非同步模式 (EAP) ,自.NET 2.0引入,現在也已經不推薦使用
3、基於任務的非同步模式 (TAP),自.NET 4.5引入,使用await/asnyc去完成非同步IO操作,可以說是C#的一個特色,也是現在微軟非同步編程的最佳實踐。
如果你還在使用System.Net.Sockets.Socket編程的話,建議你遷移到System.Net.Sockets.TcpListener和System.Net.Sockets.TcpClient上來,後者不僅對Socket進行了友好封裝,也支持TAP非同步編程。
⑩ 什麼是非同步編程
傳統的同步編程是一種請求響應模型,調用一個方法,等待其響應返回.
非同步編程就是要重新考慮是否需要響應的問題,也就是縮小需要響應的地方。因為越快獲得響應,就是越同步化,順序化,事務化,性能差化。
非同步編程通常是通過fire and forget方式實現,發射事件後即忘記,做別的事情了,無需立即等待剛才發射的響應結果了。(發射事件的地方稱為生產者,而將在另外一個地方響應事件的處理者稱為消費者).非同步編程是一種事件驅動編程,需要完全改變思路,將「請求響應」的思路轉變到「事件驅動」思路上,是一種軟體編程思維的轉變.下面幾種你看參考一下
1、非同步編程模型 (APM) 模式(也稱為 IAsyncResult 模式),其中非同步操作要求 Begin 和 End 方法(例如,非同步寫操作的 BeginWrite 和 EndWrite)。對於新的開發工作不再建議採用此模式。
2、基於事件的非同步模式 (EAP) 需要一個具有 Async 後綴的方法,還需要一個或多個事件、事件處理程序、委託類型和 EventArg 派生的類型。EAP 是在 .NET Framework 2.0 版中引入的。對於新的開發工作不再建議採用此模式。
3、基於任務的非同步模式 (TAP),該模式使用一個方法表示非同步操作的啟動和完成。.NET Framework 4 中引入了 TAP,並且是 .NET Framework 中非同步編程的建議方法。