簡體   English   中英

使用單個線程進行異步處理

[英]Asynchronous processing with a single thread

即使閱讀http://krondo.com/?p=1209異步調用是否始終創建/調用新線程? 我仍然對如何在固有的單線程系統上提供異步調用感到困惑。 到目前為止,我將解釋我的理解,並指出我的疑慮。

我讀到的一個例子是描述提供異步處理請求的TCP服務器 - 用戶會調用方法,例如get(Callback c)並且稍后會調用回調。 現在,我的第一個問題 - 我們已經有兩個系統,一個服務器和一個客戶端。 這不是我的意思,因為事實上我們至少有兩個線程 - 一個在服務器端,一個在客戶端端。

我讀的另一個例子是JavaScript,因為這是使用Node.js的單線程異步系統的最突出的例子。 我無法理解的是,也許用Java思考,是這樣的:如果我執行下面的代碼(道歉是錯誤的,可能是惡劣的語法):

function foo(){
    read_file(FIle location, Callback c) //asynchronous call, does not block
    //do many things more here, potentially for hours
}

對read文件的調用執行(sth)並返回,允許我的其余函數執行。 既然只有一個線程,即執行我的函數的線程,那么同一個線程(執行我的東西的唯一一個線程)將如何從磁盤讀取字節?

基本上,在我看來,我錯過了一些基本機制,就像某種類型的循環調度程序一樣,本質上是單線程的,可能會將任務拆分為較小的或調用多線程組件,這些組件會產生一個線程,讀取文件。

提前感謝所有評論並指出我在路上的錯誤。

更新 :感謝所有回復。 幫助我解決這個問題的更多好消息來源是:

  1. http://www.html5rocks.com/en/tutorials/async/deferred/
  2. http://lostechies.com/johnteague/2012/11/30/node-js-must-know-concepts-asynchrounous/
  3. http://www.interact-sw.co.uk/iangblog/2004/09/23/threadless(.NET
  4. http://ejohn.org/blog/how-javascript-timers-work/ (計時器的內在函數)
  5. http://www.mobl-lang.org/283/reducing-the-pain-synchronous-asynchronous-programming/

真正的答案是它取決於你所說的“單線程”。

多任務處理有兩種方法:協作和中斷驅動。 Cooperative,這是你引用的其他StackOverflow項目所要求的,它要求例程明確放棄處理器的所有權,以便它可以做其他事情。 事件驅動系統通常以這種方式設計。 優點是管理起來要容易得多,並且避免了大部分沖突訪問數據的風險,因為任何時候只有一大塊代碼在執行。 缺點是,因為一次只做一件事,所以一切都必須設計得相當快,或者分解成塊(通過像yield()調用這樣的顯式暫停),或系統在該事件完全處理之前,它似乎會凍結。

另一種方法 - 線程或進程 - 主動使處理器遠離運行代碼塊,在完成其他操作時暫停它們。 這實現起來要復雜得多,並且需要更加謹慎的編碼,因為您現在可能會同時訪問共享數據結構,但功能更強大 - 做得更好 - 更加強大和響應更快。

是的,兩種情況都確實涉及調度程序。 在以前的版本中,調度程序只是旋轉直到事件到達(從操作系統和/或運行時環境傳遞,這是隱式的另一個線程或進程)並在處理下一個到達之前調度該事件。

我在JavaScript中的想法是有一個包含事件的Queue。 在舊的Java生產者/消費者的說法中,有一個消費者線程從這個隊列中拉出東西並執行注冊接收當前事件的每個函數。 異步調用(AJAX請求完成),超時或鼠標事件等事件一旦發生就會被推送到隊列。 單個“消費者”線程將它們從隊列中拉出並找到任何感興趣的函數然后執行它們,它不能到達下一個事件,直到它完成調用當前注冊的所有函數。 因此,如果你有一個永遠不會完成的處理程序,隊列就會填滿 - 據說它被“阻止”了。

系統有多個線程(它至少有一個生產者和一個消費者),因為某些事件會生成事件以進入隊列,但作為事件處理程序的作者,您需要知道事件是在單個線程中處理的如果你進入緊密循環,你將鎖定唯一的消費者線程並使系統無響應。

所以在你的例子中:

 function foo(){
    read_file(location, function(fileContents) {
        // called with the fileContents when file is read
    }     
    //do many things more here, potentially for hours
 }

如果您按照您的意見說並執行可能持續數小時 - 即使文件已被讀取,處理fileContents的回調也不會激活數小時。 一旦你點擊foo()的最后一個消息線程就完成了這個事件,並且可以處理下一個事件,它將用文件內容執行注冊的回調。

HTH

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM