好吧,在我們開始之前,讓我清理並承認本文的標題有點聳人聽聞! JavaScript實際上沒有多線程功能,JavaScript程序員無能為力。在所有瀏覽器中 - 除了Google Chrome - JavaScript都以單個執行線程運行,這就是它的方式。
> 但是,我們能做的是模擬多線程,這在多線程環境中帶來了一個好處之一:它允許我們運行極其密集的代碼。這是代碼,否則將凍結瀏覽器並在Firefox中生成其中一個“反應式腳本”警告。 > 鑰匙要點
,但有時不是。有時根本無法避免特定操作的強度,而根本沒有在JavaScript中進行。 在給定情況下,這可能是最好的解決方案;也許在應用程序中的某些處理需要移至服務器端,在該服務器端,它具有更多的處理能力,通常可以使用,以及真正的線程執行環境(Web服務器)。
>但最終您可能會發現這不是一個選擇的情況 - JavaScript簡單地
必須能夠做某事或該死。這就是我在開發Firefox擴展時發現自己的情況。
該擴展名的核心是測試適用於頁面的CSS選擇器的能力,以查看是否實際使用它們。此的本質是使用Dean Edwards'Base2:
>肯定足夠直接。但是agetall()本身非常強烈,就像它一樣- 要解析和評估任何CSS1或CSS2選擇器,然後走整個DOM樹尋找匹配;並且擴展程序是為
>
一個簡單的測試用例for(var i=0; i<selectors.length; i++) <br> { <br> if(base2.DOM.Document.matchAll <br> (contentdoc, selectors[i]).length > 0) <br> { <br> used ++; <br> } <br> else <br> { <br> unused ++; <br> } <br> }
>讓我們通過一個簡單的測試案例來證明問題,涉及兩個迭代級別;內部層面故意太密集,因此我們可以創建比賽條件,而外部層面相當短,因此它可以模擬主代碼。這就是我們所擁有的:
>我們從簡單的表單(這是測試代碼,而不是生產)開始測試,並獲取輸出現在,讓我們在Firefox中運行該代碼(在這種情況下,在2GHz MacBook上使用Firefox 3)……並且正如預期的那樣,瀏覽器UI在運行時凍結(例如,不可能,例如不可能按刷新並放棄該過程) 。大約90次迭代後,Firefox產生了一個“反應式腳本”警告對話框。
function process() <br> { <br> var above = 0, below = 0; <br> for(var i=0; i<200000; i++) <br> { <br> if(Math.random() * 2 > 1) <br> { <br> above ++; <br> } <br> else <br> { <br> below ++; <br> } <br> } <br> } <br> <br> <br> function test1() <br> { <br> var result1 = document.getElementById('result1'); <br> <br> var start = new Date().getTime(); <br> <br> for(var i=0; i<200; i++) <br> { <br> result1.value = 'time=' + <br> (new Date().getTime() - start) + ' [i=' + i + ']'; <br> <br> process(); <br> } <br> <br> result1.value = 'time=' + <br> (new Date().getTime() - start) + ' [done]'; <br> }如果我們允許它繼續下去,在另外90個迭代後,Firefox再次產生相同的對話框。在這方面,Safari 3和Internet Explorer 6的行為類似,並具有凍結的UI和一個警告對話框的閾值。在Opera中沒有這樣的對話框 - 它只是繼續運行代碼直到完成代碼 - 但是瀏覽器UI類似地凍結了直到完成任務。
顯然,在實踐中我們無法運行代碼。因此,讓我們重新開始並使用異步計時器進行外循環:
>現在讓我們再次運行……這一次我們會收到完全不同的結果。該代碼需要一段時間才能完成,但是它可以一直成功地運行到末端,而沒有UI凍結,並且沒有警告過度緩慢的腳本。
for(var i=0; i<selectors.length; i++) <br> { <br> if(base2.DOM.Document.matchAll <br> (contentdoc, selectors[i]).length > 0) <br> { <br> used ++; <br> } <br> else <br> { <br> unused ++; <br> } <br> }>查看測試頁面
(繁忙的標誌用於防止計時器實例發生碰撞。如果我們已經在下一次迭代時已經處於子過程中的中間,我們只需等待以下迭代,從而確保只有一個子過程一次運行。)
>因此,您可以看到,儘管我們可以在
> Inner過程中所做的工作仍然很小,但
的次數>我們可以運行該過程是無限的:我們可以運行該過程外循環基本上永遠是永遠的,瀏覽器將永遠不會凍結。
>更喜歡它 - 我們可以在野外使用它。
>我已經可以聽到反對者了。實際上,我可能自己是一個人:您為什麼要這樣做 - 什麼樣的瘋子堅持將JavaScript推到從未被設計為去的所有這些地方?您的代碼太強烈了。這是工作的錯誤工具。如果您必須跳過這類箍,那麼您的應用程序的設計從根本上是錯誤的。
>我已經提到了一個例子,我必須找到一種繁重的腳本工作的方法。就是這樣,或者整個想法必須放棄。如果您不相信該答案,那麼本文的其餘部分也可能對您不吸引您。>上的遊戲
我在這裡說的是了解遊戲規則所需的代碼,然後可以評估情況和策略,以便在該遊戲中擊敗您。複雜的東西。
為了說明,我要看一個我在一邊開發的項目一段時間。 “小時”是指三年,其中大多數是在理論上工作的高原上花費的,但太強烈了,無法使用……直到我想到了這種方法。該遊戲是一個基於顏色和形狀匹配的競爭難題。
>
總結一下:您通過相鄰的形狀和顏色匹配來整個過程。例如,如果您開始使用綠色三角形 - 那麼您可以移至任何其他三角形或任何其他綠色形狀。您的目標是到達中間的水晶,然後將其帶到板的另一側,而對手則嘗試這樣做。您也可以從對手那裡竊取水晶。
因此,我們有確定運動的邏輯規則,我們還可以看到策略的出現。例如,為了避免讓對手到達水晶,或從您那裡偷走它 - 您可能會選擇阻止它們的動作,或者嘗試在他們無法到達的地方完成。
計算機的工作是在任何給定的情況下找到最佳的動作,因此讓我們查看摘要偽代碼中的該過程:>
for(var i=0; i<selectors.length; i++) <br> { <br> if(base2.DOM.Document.matchAll <br> (contentdoc, selectors[i]).length > 0) <br> { <br> used ++; <br> } <br> else <br> { <br> unused ++; <br> } <br> }我們評估了一種策略,如果這給了我們一個好的舉動,那麼我們就完成了;否則,我們將評估另一種策略,依此類推,直到我們有動作,或者得出結論,我們必須通過。
>每個策略功能都運行一個昂貴的過程,因為它必須評估董事會中的每個職位以及潛在的未來位置,可能會根據各種因素進行多次。該示例只有三種策略,但是在真實的遊戲中,有數十種可能性,每個可能性都昂貴。
>>單獨評估中的任何一個都很好,但是所有這些評估都可以連續運行,使過度激烈的過程凍結了瀏覽器。
>>因此,我所做的是將主代碼拆分為“謹慎”任務
,每個任務都是用開關語句選擇的,然後使用異步計時器進行迭代。這樣做的邏輯距離那些小時候的那些選擇您曾經有過的冒險書的邏輯不到一百萬英里,在那裡,每個任務都以實時的選擇結束,直到我們到達終點:此代碼比原始代碼明顯高得多,因此,如果減少代碼大小是唯一的命令,這顯然不是要走的路。
但是,我們在這裡要做的是創建一個沒有天花板的執行環境,即,在復雜性和長度方面沒有上限的過程;這就是我們所做的。function process() <br> { <br> var above = 0, below = 0; <br> for(var i=0; i<200000; i++) <br> { <br> if(Math.random() * 2 > 1) <br> { <br> above ++; <br> } <br> else <br> { <br> below ++; <br> } <br> } <br> } <br> <br> <br> function test1() <br> { <br> var result1 = document.getElementById('result1'); <br> <br> var start = new Date().getTime(); <br> <br> for(var i=0; i<200; i++) <br> { <br> result1.value = 'time=' + <br> (new Date().getTime() - start) + ' [i=' + i + ']'; <br> <br> process(); <br> } <br> <br> result1.value = 'time=' + <br> (new Date().getTime() - start) + ' [done]'; <br> }
這個模式可以無限期地擴展
,具有數百甚至數千個任務。它可能需要很長時間才能運行,但是將其運行,並且只要每個個體
任務都不太強烈,它將在不殺死瀏覽器的情況下運行。無返回的路徑
這種方法的強度也是它的主要弱點:由於內部函數是異步的,因此我們無法從外部函數中返回值。因此,例如,我們無法做到這一點(或者,我們可以,但沒有意義): checksomething()函數將始終始終返回false,因為內部函數是異步的。外部功能將在內部功能的第一次迭代發生之前返回! 下一個示例同樣毫無意義: >我們不超出外部功能的範圍,因此我們無法從中返回;該返回值無用地消失在以太中。 我們的> 在這裡做的是從AJAX編碼技術中取出葉子,並使用回調函數(在此示例中,我稱為“ oncomplete”): 因此,當我們調用checkSomething()時,我們將匿名函數作為其參數,並且當作業完成時,該函數以最終值調用: 優雅?不,但是功能強大嗎?是的。這就是重點。使用此技術,我們可以編寫原本不可能的腳本。 >在我們的套件中,我們現在有一種方法來解決以前擺脫可能性領域的JavaScript項目。我開發了這種模式的遊戲具有相當簡單的邏輯,因此一個相當簡單的brain>,但對於常規迭代而言,它仍然太多了。還有很多其他遊戲需要更多的影響力! 我的下一個計劃是使用此技術實現JavaScript國際象棋引擎。國際象棋具有各種可能的場景和戰術,導致決策可能需要很長時間才能計算,遠遠超過沒有這種技術的可行性。即使創建最基本的思維機器也需要進行激烈的計算,我承認對可能性感到非常興奮。 如果我們能像這樣刪除技巧,誰能說出可能?自然語言處理,啟發式方法……也許我們有在JavaScript中開發人工智能的基礎! >為什麼javascript支持多本身? >在JavaScript中使用Web Worker進行多線程,您需要創建一個新的Worker對象並指定在工作線程中執行要執行的JavaScript文件。然後,您可以使用tostmessage方法與工作線程進行通信,並使用onMessage事件處理程序從其接收消息。 多插圖可能會使您的JavaScript代碼可能使您的JavaScript代碼。更快,但這取決於要執行的任務的性質。對於CPU密集型任務,多線程可以通過允許並行執行任務來顯著提高性能。但是,對於I/O結合的任務,多線程的好處不太明顯,因為這些任務通常受到CPU控制以外的因素的限制,例如網絡速度。 for(var i=0; i<selectors.length; i++) <br>
{ <br>
if(base2.DOM.Document.matchAll <br>
(contentdoc, selectors[i]).length > 0) <br>
{ <br>
used ++; <br>
} <br>
else <br>
{ <br>
unused ++; <br>
} <br>
}
function process() <br>
{ <br>
var above = 0, below = 0; <br>
for(var i=0; i<200000; i++) <br>
{ <br>
if(Math.random() * 2 > 1) <br>
{ <br>
above ++; <br>
} <br>
else <br>
{ <br>
below ++; <br>
} <br>
} <br>
} <br>
<br>
<br>
function test1() <br>
{ <br>
var result1 = document.getElementById('result1'); <br>
<br>
var start = new Date().getTime(); <br>
<br>
for(var i=0; i<200; i++) <br>
{ <br>
result1.value = 'time=' + <br>
(new Date().getTime() - start) + ' [i=' + i + ']'; <br>
<br>
process(); <br>
} <br>
<br>
result1.value = 'time=' + <br>
(new Date().getTime() - start) + ' [done]'; <br>
}
<form action=""> <br>
<fieldset> <br>
<input type="button" value="test1" onclick="test1()" /> <br>
<input type="text" /> <br>
</fieldset> <br>
</form> <br>
function test2() <br>
{ <br>
var result2 = document.getElementById('result2'); <br>
<br>
var start = new Date().getTime(); <br>
<br>
var i = 0, limit = 200, busy = false; <br>
var processor = setInterval(function() <br>
{ <br>
if(!busy) <br>
{ <br>
busy = true; <br>
<br>
result2.value = 'time=' + <br>
(new Date().getTime() - start) + ' [i=' + i + ']'; <br>
<br>
process(); <br>
<br>
if(++i == limit) <br>
{ <br>
clearInterval(processor); <br>
<br>
result2.value = 'time=' + <br>
(new Date().getTime() - start) + ' [done]'; <br>
} <br>
<br>
busy = false; <br>
} <br>
<br>
}, 100); <br>
<br>
}
android shove silicon綿羊的夢想?
>
> javascript中多線程的限制是什麼? 🎜>雖然可以通過Web Worker來實現JavaScript中的多線程,但重要的是要注意,這些工人無法訪問DOM或其他Web API。它們僅限於幾種可以來回發送到主線程的數據類型。另外,每個工人都是一個單獨的實例,因此他們不共享範圍或任何全局變量。
>如何在JavaScript中使用Web Worker進行多線程?
>多插圖可以使我的JavaScript代碼更快?
我可以在JavaScript中使用多線程進行前端開發嗎? ,您可以在JavaScript中使用多線程進行前端開發。但是,重要的是要注意,啟用多線程的Web工作人員無法訪問DOM或其他Web API。因此,它們通常用於不涉及操縱DOM或與網頁進行交互的任務,例如執行計算或處理數據。
以上是JavaScript中的多線程的詳細內容。更多資訊請關注PHP中文網其他相關文章!