非同步程式設計從很久之前就開始學習,但是發現只要是不總結的東西,總是特別容易忘記,而且沒有深入的學習和實踐,對技術的細節和原理也是理解不深,所以這次一定要把最新學到的,和原來記憶不清的知識從新梳理一遍。執行緒,程序和應用程式域的基本知識在這有總結:
同步非同步和阻塞非阻塞,有簡單理解也有詳細解釋,同時對應到linux的五種網路模型,這裡簡單解釋一下:
「阻塞」與"非阻塞"與"同步"與「非同步"不能簡單的從字面理解,提供乙個從分布式系統角度的回答。
1.同步與非同步:同步和非同步關注的是訊息通訊機制(synchronous
communication/ asynchronous communication)所謂同步,就是在發出乙個呼叫時,在沒有得到結果之前,該呼叫就不返回。但是一旦呼叫返回,就得到返回值了。
換句話說,就是由呼叫者主動等待這個呼叫的結果。而非同步則是相反,呼叫在發出之後,這個呼叫就直接返回了,所以沒有返回結果。換句話說,當乙個非同步過程呼叫發出後,呼叫者不會立刻得到結果。而是在呼叫發出後,被呼叫者通過狀態、通知來通知呼叫者,或通過**函式處理這個呼叫。
典型的非同步程式設計模型比如node.js舉個通俗的例子:你打**問書店老闆有沒有《分布式系統》這本書,如果是同步通訊機制,書店老闆會說,你稍等,」我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。而非同步通訊機制,書店老闆直接告訴你我查一下啊,查好了打**給你,然後直接掛**了(不返回結果)。然後查好了,他會主動打**給你。在這裡老闆通過「回電」這種方式來**。
2.阻塞與非阻塞阻塞和非阻塞關注的是程式在等待呼叫結果(訊息,返回值)時的狀態.阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起。呼叫執行緒只有在得到結果之後才會返回。非阻塞呼叫指在不能立刻得到結果之前,該呼叫不會阻塞當前執行緒。
在我的理解中,.net的非同步程式比較舊的有手動建立thread,非同步的委託呼叫。到了.net framwork 4.5以後,有了async和await,相對於原始的非同步程式設計,變得更加簡潔和易讀,但是要完全搞懂還是需要深入學習一下。
static void main(string args)
", thread.currentthread.managedthreadid);
printer p = new printer();
waitcallback workitem = new waitcallback(printnumbers);
for (int i = 0; i < 10; i++)
console.readline();
}static void printnumbers(object state)
waitcallback 委託指向有單個object型別的引數且無返回值的方法。
threadpool.queueuserworkitem()方法使用執行緒池中的工作者執行緒排隊執行乙個方法。
使用執行緒池的好處主要是:
在某些情況下我們還是有限使用手動執行緒管理:
(以上內容大多是抄書,還沒有在專案中有深刻的體會,以後再補充)
task 的內容和後面的async、await關係比較密切,就多查了一下資料,內容很多,只能慢慢寫。大綱:
task和taskfactory
start,run,wait,waitall,wenall
錯誤捕捉
強制停止
2.2.1 task初始化
建立task有三種方式:
task t1=new task(mymethod);
task t2= task.factory.startnew(mymethod);
task t3=task.run(mymethod);
msdn說處於效能考慮,推薦使用後兩種方式。而且後兩種方式不需要手動start()
2.2.2 start、run、wait、waitall、wenall
有幾個比較重要的方法,摘抄一下msdn的定義。
2.2.3 異常處理
在非同步程式設計中,主線程是無法捕獲工作者執行緒丟擲的exception,目前處理異常有兩種思路,一種是用continuewith()在下乙個task處理異常,另一種是包裝到主線程,由主線程處理。
下面是使用contiuewith()
static void main(string args)
發生錯誤");
});t1.start();
task t2 = t1.continuewith((task) =>
});console.readkey();
}
使用await包裝到主線程處理:
static void main(string args)
);
t.start();
task ttend = t.continuewith((task) =>
, taskcontinuationoptions.onlyonfaulted);
try
catch (aggregateexception err)
來自:
異常內容:", item.innerexception.gettype(),
environment.newline, item.innerexception.source,
environment.newline, item.innerexception.message);
} }
console.writeline("主線程馬上結束");
console.readkey();
}
使用事件通知包裝到主線程:
static event eventhandleraggregateexceptioncatched;
public class aggregateexceptionargs: eventargs
} static void main(string args)
catch (exception err)
; aggregateexceptioncatched(null, errargs);
} });
t.start();
console.writeline("主線程馬上結束");
console.readkey();
} static void program_aggregateexceptioncatched(object sender, aggregateexceptionargs e)
來自:異常內容:",
item.gettype(), environment.newline, item.source,
environment.newline, item.message);
} }
大綱:
3.1.1 概念和簡介
3.1.2 使用示例
微軟msdn上的執行順序圖。
class program
private static async taskgetlengthasync()
private static taskgetstringasync());}
}
測試**執行結果為:
下面是個人的理解,如果用await 標記等待非同步方法,那麼這裡就是非同步阻塞的,如果用task物件去接受非同步方法返回的task,就是非同步非阻塞的,而且真正的非同步**,基本上是在task.run()內部才開始真正在其他執行緒上執行。
3.1.3 專案實戰
專案中我要實現的是乙個多執行緒爬蟲,尤其是在每個站點的列表頁爬取完成後,需要爬取20-30個詳情頁,目前只做了詳情頁的多執行緒。
3.1.4 原理
執行的原理其實是task+狀態機。這裡就不詳細研究了,貼上一下學習時用到的鏈結。
發散思維淺說
在策劃乙個系統的時候,我們往往發現人類對縝密思考還有很長的路要走。本身也是若干簡單而成熟的技術組成的系統,總要不斷的修正,再想想,再看看,再研究研究,在比較比較,再參詳參詳,再考慮考慮 大俠並非自詡什麼邏輯學專家,這裡只是簡單對發散思維做一些淺述,希望對新手和即將步入大學的弟妹們有個好的啟蒙 對於嚴...
網路 DNS淺說
一般普通的撥號使用者當撥號成功後,會自動獲得運營商分配的ip和dns伺服器位址,一般不需要我們手動設定 而專線使用者由於是固定ip,如果只設定了ip位址,是無法發開網頁的,必須手工進行設定,如果使用路由器了,最好在路由器裡面設定。一般情況dns是不需要我們自己配置的,只有特定的情況才會去配置,下面列...
淺說預解析
全域性作用域 當瀏覽器載入html頁面的時候,首先會提供乙個全域性js 執行的環境.這個環境就是全域性作用域 window var num 12 var obj function fn fn 預解析 在當前作用域中,js 執行之前瀏覽器首先會預設把所有帶var和function的進行提前的宣告或者定...