>웹 프론트엔드 >JS 튜토리얼 >JavaScript의 멀티 스레딩

JavaScript의 멀티 스레딩

Christopher Nolan
Christopher Nolan원래의
2025-02-25 11:37:12887검색

JavaScript의 멀티 스레딩 좋아, 우리가 시작하기 전에, 내가 깨끗하게 와서이 기사의 제목이 약간 감각적이라는 것을 인정하겠습니다! JavaScript에는 실제로 멀티 스레딩 기능이 없으며 JavaScript 프로그래머가이를 변경하기 위해 할 수있는 일은 없습니다. 모든 브라우저에서 - Google Chrome을 제외하고 JavaScript는 단일 실행 스레드에서 실행됩니다. 이것이 바로 그 방법입니다. 그러나, 우리가 할 수있는 것은

멀티 스레딩을 시뮬레이션하는 것입니다. 이것은 그렇지 않으면 브라우저를 동결하고 Firefox에서 "비 응답 ​​스크립트"경고 중 하나를 생성하는 코드입니다. 키 테이크 아웃

JavaScript는 기본적으로 멀티 스레딩을 지원하지 않지만 비동기 타이머와 웹 워커를 통해 시뮬레이션하여 브라우저를 동결시키지 않고 집중 계산을 허용합니다. 비동기 타이머는 작업을 작은 청크로 분해하여 시간이 지남에 따라 코드가 실행되는 방식을 관리함으로써 브라우저가 응답하지 않도록합니다. 웹 워커는 사용자 인터페이스에 영향을주지 않고 배경 작업을 수행 할 수있는 JavaScript의 기능을 향상시킵니다. DOM과 상호 작용하거나 특정 웹 API를 사용할 수는 없습니다. 브라우저를 잠그는 복잡한 작업의 경우 비동기 타이머를 사용하기위한 리팩토링 코드는 UI 동결을 방지하고 리소스 집약적 프로세스를보다 효과적으로 관리 할 수 ​​있습니다.

JavaScript의 단일 스레드 특성에도 불구하고 비동기 프로그래밍 및 웹 작업자와 같은 기술은 개발자에게 다중 스레딩과 같은 시나리오를 처리 할 수있는 강력한 도구를 제공하여 집중 작업의 성능을 향상시킵니다.

시간은 아무도 기다리지 않습니다 그것은 비동기 타이머 사용에 대한 모든 힌지입니다. 비동기 타이머 내에서 반복적 인 코드를 실행하면 브라우저의 스크립트 통역사에게 각 반복을 처리 할 시간을 제공합니다. 효과적으로, ITERATOR를위한 A 내부의 코드는 통역사에게 모든 것을 바로 수행하도록 요청하고 있습니다. 그러나 비동기 타이머 내부의 동일한 코드가 코드를 작고 신중한 덩어리로 나누고 있습니다. 즉,“이 코드를 최대한 빨리 실행하십시오.” - 대기 -“가능한 한 빨리이 코드를 실행하십시오”등, n 시간. 트릭은 각 반복 내부의 코드가 작고 간단하다는 것입니다. 통역사가 타이머 속도 내에서 완전히 처리 할 수있을 정도로 간단하다는 것입니다. 해당 요구 사항이 충족되면 전체 코드가 얼마나 강렬한지는 중요하지 않습니다. 왜냐하면 우리는 한 번에 모두 실행하도록 요구하지 않기 때문입니다.“너무 강렬한”얼마나 강렬한가? 정상적으로, 너무 집중적 인 것으로 판명 된 스크립트를 작성한다면, 나는 그것을 다시 엔지니어링하는 것을 볼 것입니다. 이러한 중대한 둔화는 일반적으로 코드의 문제 또는 응용 프로그램 설계에 더 깊은 문제를 나타냅니다.

그러나 때로는 그렇지 않습니다. 때로는 특정 작업의 강도를 피할 수있는 방법이 없습니다. 주어진 경우에서 최상의 솔루션 일 수 있습니다. 아마도 애플리케이션의 일부 처리는 서버 측으로 이동해야 할 것입니다. 일반적으로 작업 할 수있는 처리 능력이 더 많으며 실제로 실행 된 실행 환경 (웹 서버).
. 그러나 결국 옵션이 아닌 상황을 찾을 수 있습니다. JavaScript가 단순히

가 무언가를 할 수 있거나 저주를 받아야하는 상황을 찾을 수 있습니다. 그것이 Firefox 확장을 개발할 때 자신이 찾은 상황, Dust-Me Selectors. 해당 확장의 핵심은 페이지에 적용되는 CSS 선택기를 테스트하여 실제로 사용 중인지 확인하는 기능입니다. 이것의 본질은 Dean Edwards의 Matchall () 메소드를 사용한 일련의 평가 세트입니다.

충분히 간단합니다. 그러나 matchall () 자체는 CSS1 또는 CSS2 선택기를 구문 분석하고 평가 한 다음 전체 Dom 트리를 걸어 다니는 일치를 찾고 있습니다. 그리고 확장자는 각각의 개별 선택기

에 대해이를 수행하며, 그 중 수천 개가있을 수 있습니다. 이 과정은 표면에서 너무 단순하기 때문에 전체 브라우저가 발생하는 동안 얼어 붙을 수 없을 정도로 집중적 일 수 있습니다. 그리고 이것이 우리가 찾은 것입니다.

브라우저를 잠그는 것은 분명히 옵션이 아니므로 이것이 전혀 작동하지 않으면 오류없이 실행하는 방법을 찾아야합니다.

. 간단한 테스트 케이스 두 가지 수준의 반복과 관련된 간단한 테스트 케이스의 문제를 입증하겠습니다. 내부 레벨은 고의적으로 너무 집중적이므로 레이스 조건을 만들 수 있지만 외부 레벨은 상당히 짧아서 기본 코드를 시뮬레이션합니다. 이것이 우리가 가진 것입니다 :

우리는 테스트를 시작하고 간단한 형태 (이것은 생산이 아닌 테스트 코드이므로 인라인 이벤트 핸들러 사용에 의지하는 것을 용서해주십시오) : .

이제 Firefox에서 해당 코드를 실행합시다 (이 경우 2GHz MacBook의 Firefox 3)… 예상대로 브라우저 UI는 실행 중에 얼어 붙습니다 (예 : 새로 고침을 누르고 프로세스를 포기하는 것이 불가능합니다). . 약 90 회 반복 후 Firefox는 "응답하지 않는 스크립트"경고 대화 상자를 생성합니다.

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>
}
우리가 계속 허용되면, 또 다른 90 회 반복 후에 Firefox는 다시 동일한 대화 상자를 생성합니다. Safari 3과 Internet Explorer 6은 이와 관련하여 비슷하게 행동하며, 얼어 붙은 UI 및 경고 대화 상자가 생성되는 임계 값과 비슷합니다. 오페라에는 그러한 대화가 없다 - 그것은 완료 될 때까지 코드를 계속 실행한다. 그러나 브라우저 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>
}
횟수

우리는 이제 그 과정을 실행할 수 있습니다. OUTER 루프는 기본적으로 영원히, 브라우저는 결코 얼지 않을 것입니다.

그것은 훨씬 더 비슷합니다 - 우리는 이것을 야생에서 사용할 수 있습니다.

당신은 미쳤습니다! 나는 이미 물체를들을 수 있습니다. 사실, 나는 나 자신이 될 수 있습니다 : 왜 당신은 이것을 하시겠습니까? 코드가 너무 강렬합니다. 이것은 작업에 잘못된 도구입니다. 이런 종류의 후프를 뛰어 넘어야한다면 응용 프로그램의 디자인이 근본적으로 잘못되었습니다.

나는 이미 무거운 스크립트가 작동하는 방법을 찾아야 할 예제를 이미 언급했습니다. 그것은 또는 전체 아이디어를 포기해야했습니다. 그 대답에 확신이 없다면, 기사의 나머지 부분은 당신에게 호소하지 않을 수 있습니다. . 그러나 만약 당신이 또는 적어도, 당신이 확신을 갖고있을 경우, 여기에 실제로 집에 못 박는 또 다른 예는 다음과 같습니다. JavaScript를 사용하여 컴퓨터에 대항 할 수있는 게임을 작성하십시오.

on 게임 내가 여기서 말하는 것은 게임의 규칙을 이해하는 데 필요한 코드이며, 그 게임에서 당신을 이길 수 있도록 상황과 전술을 평가할 수 있습니다. 복잡한 것들. 를 설명하기 위해, 나는 잠시 동안 내가 개발 한 프로젝트를 살펴 보겠습니다. “Little While”이라는 의미는 를 의미합니다. 대다수는 게임이 이론적으로 작동했지만이 접근법을 생각할 때까지 사용하기에는 너무 강렬했습니다. 이 게임은 색상 및 모양 매칭을 기반으로 한 경쟁 퍼즐입니다.

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> }를 확장 할 수 있습니다. 실행하는 데 시간이 오래 걸릴 수 있지만 실행할 수 있으며, 각 개인

작업이 너무 강하지 않은 한 브라우저를 죽이지 않고 실행됩니다.

. 리턴 없음 이 접근법의 강점은 또한 주요 약점입니다. 내부 기능은 비동기식이기 때문에 외부 기능에서 값을 반환 할 수 없습니다. 예를 들어, 우리는 이것을 할 수 없지만 (또는 오히려 우리는 할 수 있지만 아무런 의미가 없을 것입니다) : .
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>
}
내부 함수가 비동기식이기 때문에 checksomething () 함수가 항상

항상 가 false를 반환합니다. 내부 기능의 첫 번째 반복이 발생하기 전에 외부 기능이 돌아갑니다! 이 다음 예제는 비슷하게 무의미합니다

우리는 외부 기능의 범위를 벗어 났으므로 우리는 그것에서 돌아올 수 없습니다. 그 반환 값은 에테르로 쓸모없는 사라집니다.

우리가 function process()
{
 var above = 0, below = 0;
 for(var i=0; i<200000; i++)
 {
   if(Math.random() * 2 > 1)
   {
     above ++;      
   }
   else
   {
     below ++;
   }
 }
}


function test1()
{
 var result1 = document.getElementById('result1');
 
 var start = new Date().getTime();
   
 for(var i=0; i<200; i++)
 {
   result1.value =  'time=' +  
     (new Date().getTime() - start) + ' [i=' + i + ']';
   
   process();
 }
 
 result1.value = 'time=' +  
   (new Date().getTime() - start) + ' [done]';
} 할 수있는 일은 Ajax 코딩 기술에서 잎을 가져 와서 콜백 함수를 사용하는 것입니다 (이 예에서는“oncomplete”라고 부릅니다) :

.

따라서 checksomething ()을 호출 할 때 익명 기능을 인수로 전달하고 해당 기능은 작업이 완료 될 때 최종 값으로 호출됩니다.

우아함? 아니요.하지만 강력하게 기능적입니까? 예. 그리고 그것이 요점입니다. 이 기술을 사용하면 불가능한 스크립트를 쓸 수 있습니다. 안드로이드가 실리콘 양의 꿈을 꾸는가?

키트 에이 기술을 사용하여 이제는 이전에 가능성이없는 자바 스크립트 프로젝트를 다루는 수단을 가지고 있습니다. 내가이 패턴을 개발 한 게임은 상당히 간단한 논리를 가지고 있으므로 상당히 간단한
<form action=""> <br>
  <fieldset> <br>
    <input type="button" value="test1" onclick="test1()" /> <br>
    <input type="text"  /> <br>
  </fieldset> <br>
</form> <br>

이지만 여전히 기존의 반복에는 너무 많았습니다. 그리고 더 많은 영향력이 필요한 다른 게임이 많이 있습니다!

다음 계획은이 기술을 사용하여 JavaScript 체스 엔진을 구현하는 것입니다. 체스는 가능한 다양한 시나리오와 전술을 가지고 있으며,이 기술이 없으면 실현 가능한 것보다 훨씬 오래 계산하는 데 매우 오랜 시간이 걸릴 수있는 결정으로 이어집니다. 가장 기본적인 사고 기계조차 만들려면 강렬한 계산이 필요하며 가능성에 대해 매우 흥분한다고 고백합니다.
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>
}
우리가 이와 같은 트릭을 풀 수 있다면 누가 가능한 것을 말해야합니까? 자연 언어 처리, 휴리스틱… 아마도 우리는 자바 스크립트로 인공 지능을 개발하기위한 빌딩 블록을 가지고있을 것입니다!이 게시물을 읽는 것을 즐겼다면 학습 가능한 것을 좋아할 것입니다. 주인으로부터 신선한 기술과 기술을 배울 수있는 곳. 회원은 웹 용 JavaScript 프로그래밍과 같은 모든 SitePoint의 eBook 및 대화식 온라인 과정에 즉시 액세스 할 수 있습니다. 이 기사에 대한 의견이 닫힙니다. JavaScript에 대한 질문이 있습니까? 우리 포럼에서 물어 보지 않겠습니까? 이미지 크레딧 : 랜든 L 피터슨 javaScript 의 멀티 스레딩에 대한 질문이 자주 묻습니다 JavaScript Multithreading에서 웹 워커의 역할은 무엇입니까? 웹 작업자는 JavaScript MultithReading에서 중요한 역할을합니다. 웹 컨텐츠가 백그라운드 스레드에서 스크립트를 실행하는 간단한 수단입니다. 작업자 스레드는 사용자 인터페이스를 방해하지 않고 작업을 수행 할 수 있습니다. 또한 xmlhttprequest를 사용하여 I/O를 수행 할 수 있습니다 (응답 XML 및 채널 속성은 항상 null이지만). 일단 생성되면, 작업자는 해당 코드에서 지정된 이벤트 핸들러에 메시지를 게시하여 작성된 JavaScript 코드에 메시지를 보낼 수 있습니다. JavaScript는 본질적으로 단일 스레드가 있지만 비동기 콜백 및 약속을 사용하여 멀티 스레딩을 처리 할 수 ​​있습니다. 이는 JavaScript 자체가 단일 스레드에서 작동하지만 향후에 실행할 작업을 예약하여 여러 작업을 동시에 수행 할 수 있도록 할 수 있음을 의미합니다. 이것은 메인 스레드가 다른 코드를 계속 실행하는 동안 백그라운드에서 처리 할 수있는 사용자 입력 또는 API 요청과 같은 작업을 처리하는 데 특히 유용합니다. javaScript에서 멀티 스레딩의 한계는 무엇입니까? 웹 작업자를 통해 JavaScript의 멀티 스크롤링을 달성 할 수 있지만 이러한 작업자는 DOM이나 다른 웹 API에 액세스 할 수 없다는 점에 유의해야합니다. 그들은 주 스레드로 앞뒤로 보낼 수있는 몇 가지 데이터 유형으로 제한됩니다. 또한 각 작업자는 별도의 인스턴스이므로 스코프 나 글로벌 변수를 공유하지 않습니다.

node.js에서 멀티 스레딩을 구현하려면 어떻게해야합니까?

node.js는 내장이 있습니다. 메인 노드 프로세스 (마스터)와 서버 포트를 공유하는 하위 프로세스 (작업자)를 생성 할 수있는 '클러스터'라는 모듈에서. 이러한 어린이 프로세스는 동시에 실행되고 다른 작업을 수행하여 멀티 스레딩을 효과적으로 구현할 수 있습니다.

JavaScript가 멀티 스크릿을 기본적으로 지원하지 않는 이유는 무엇입니까?

JavaScript는 복잡성과 잠재력을 피하기 위해 단일 스레드로 설계되었습니다. 데이터 조작 문제. 멀티 스레딩은 출력이 통제 할 수없는 다른 이벤트의 시퀀스 또는 타이밍에 의존하는 레이스 조건과 같은 문제로 이어질 수 있습니다. 스레드 간의 종속성을 다룰 필요가 없기 때문에 단일 스레드 환경을 최적화하는 것이 더 쉬울 것으로 생각되었습니다.

. JavaScript에서 멀티 스레딩에 웹 워커를 사용하는 방법

JavaScript에서 멀티 스레딩에 웹 워커를 사용하려면 새 작업자 객체를 작성하고 작업자 스레드에서 실행할 JavaScript 파일을 지정해야합니다. 그런 다음 PostMessage 메소드를 사용하여 작업자 스레드와 통신하고 OnMessage 이벤트 핸들러를 사용하여 메시지를받을 수 있습니다.

멀티 스크릿이 내 JavaScript 코드를 더 빠르게 만들 수 있습니까?

MultithReading은 잠재적으로 JavaScript 코드를 만들 수 있습니다. 더 빠르지 만 수행중인 작업의 특성에 따라 다릅니다. CPU 집약적 인 작업의 경우 멀티 스레딩은 작업을 병렬로 수행 할 수 있도록하여 성능을 크게 향상시킬 수 있습니다. 그러나 I/O- 결합 작업의 경우, 이러한 작업은 종종 네트워크 속도와 같은 CPU의 제어 외부의 요인에 의해 제한되기 때문에 멀티 스레딩의 이점은 덜 두드러집니다. 멀티 스레딩과 비동기식의 차이점은 무엇입니까? JavaScript의 프로그래밍?

멀티 스레딩 및 비동기 프로그래밍은 동시에 여러 작업을 관리하는 데 사용되는 기술입니다. 그러나 그들은 다른 방식으로 그것을합니다. 멀티 스레딩에는 여러 실행 스레드가 포함되며 각 스레드는 다른 작업을 수행합니다. 반면에 비동기 프로그래밍에는 단일 실행 스레드가 포함되지만 작업을 시작한 다음 나중에 완료하여 다른 작업을 수행 할 수 있습니다. JavaScript의 스레드간에 데이터 공유?

JavaScript의 스레드 간의 데이터 공유는 SharedArraybuffer 및 Atomics를 사용하여 달성 할 수 있습니다. SharedArrayBuffer는 기본 스레드와 작업자 스레드간에 메모리를 공유 할 수있는 반면, Atomics는 공유 메모리에서 안전한 원자 연산을 수행하는 방법을 제공합니다.

프론트 엔드 개발을 위해 JavaScript에서 멀티 스레딩을 사용할 수 있습니까? , 프론트 엔드 개발을 위해 JavaScript에서 멀티 스레딩을 사용할 수 있습니다. 그러나 멀티 스레딩을 가능하게하는 웹 작업자는 DOM 또는 기타 웹 API에 액세스 할 수 없다는 점에 유의해야합니다. 따라서 일반적으로 계산 수행 또는 데이터 처리와 같이 DOM을 조작하거나 웹 페이지와 상호 작용하지 않는 작업에 일반적으로 사용됩니다.

위 내용은 JavaScript의 멀티 스레딩의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.