2010-10-27 4 views
5

En utilisant javascript j'ai remarqué cette chose. Vous pouvez utiliserEst-ce que ce comportement de setInterval implique un comportement de multithreading en Javascript?

var i=0; 
var startingTime=new Date().getTime(); 
setInterval("foo()",1); 
function foo() { 
    i+=1; 
    if ($("#foodiv").text()==i) { 
     //we detected a doubled value (parallel execution) 
     $("#repdiv").append("[repetition on "+i+"]"); 
    } 
    $("#foodiv").html(i); 
    $("#timediv").html(Math.floor((new Date().getTime()-startingTime)/1000)); 
} 

mais comme je l'ai lu et essayer moi-même le temps n'est pas 1ms, il est au moins 10ms ou quelque chose. En fait, après 10 secondes, j'ai une valeur de i autour de 2300/2400, et pas 10000 comme prévu.

Ceci est le facteur de temps minimum possible pour la procédure ??? certainement pas. Si j'essaie ceci:

<html><head> 
<script language="javascript" type="text/javascript" src="jquery-1.4.min.js"></script> 
<script type="text/javascript"> 

var i=0; 
var startingTime=new Date().getTime(); 

setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 
setInterval("foo()",1);setInterval("foo()",1);setInterval("foo()",1); 

function foo() { 
    i+=1; 
    if ($("#foodiv").text()==i) { 
     //we detected a doubled value (parallel execution) 
     $("#repdiv").append("[repetition on "+i+"]"); 
    } 
    $("#foodiv").html(i); 
    $("#timediv").html(Math.floor((new Date().getTime()-startingTime)/1000)); 

} 
</script> 
</head> 
<body> 
<div id="foodiv"></div> (counter) 
<br/> 
<div id="timediv"></div> (seconds passed) 
<br/> 
<div id="repdiv"></div> 
<br/> 
</body> 
</html> 

Le compteur va très vite, et au bout de 10 secondes, j'ai une valeur de 12000 !!!!. C'est pour moi inexplicable, parce que l'appel n'est pas exécuté en parallèle (ou du moins nous pourrions avoir des valeurs lues doublées de i pour différents appels, en figurant dans la division repdiv).

Quelqu'un peut-il m'expliquer cela? Je sais que le processeur est très stressé par tous ces appels, mais au moins, il accélère les choses de manière surprenante.

J'ai lu toutes vos réponses et les autres quêtes du forum, et elles m'ont confirmé. Mais la vraie question est pourquoi! Pourquoi ils fixent la limite à 15ms quand je peux faire plusieurs appels séquentiels obtenant un temps beaucoup plus bas? Je suis sûr que ce système de rappel multiple n'est pas une bonne pratique, mais je peux le faire, et je peux potentiellement saturer la charge du processeur.

+5

Je ne vois pas comment ce code fonctionne, set interval prend une fonction comme premier argument, pas foo(), cela devrait ressembler plus à setInterval (foo, 1). Il vous manque également une terminaison) après votre if et append –

+0

Aussi, en supposant que le code est correct, les valeurs semblent fausses. Avec 12 minuteries, le compteur ne sera que 12 fois plus rapide, donc 600 deviendra 7200, pas 150000. Quelque chose me dit que ce n'est pas le code que l'OP a testé. – casablanca

+0

vous avez raison, j'ai édité le code plusieurs fois, et l'ai recréé à la maison, mais le concept ne change pas. Je vais répéter les choses comme je l'ai fait efficacement. Aussi, si vous remarquez que j'ai omis le code html, et que cela rend les choses plus mauvaises si vous essayez cela comme il est. – mizar

Répondre

0

La deuxième valeur transmise à la méthode setInterval est en effet une valeur minimale. Bien que 1 représente 1 milliseconde et il est peu probable que la plupart des navigateurs vous donnent exactement ce délai. Une autre réponse dit qu'il est plus probable d'être environ 15 millisecondes.

Même ainsi, le deuxième élément étant une valeur minimale explicite correctement le premier échantillon.

Le deuxième exemple est également expliqué par ce comportement. Chacune des méthodes setInterval que vous appelez enregistre un rappel complètement distinct. Ils ont chacun un minimum de 1, mais aucune dépendance les uns envers les autres. Il est donc parfaitement valable que tous tirent dans le même intervalle de 1 milliseconde (tant que chacun attend 1 milliseconde avant de re-tirer).

+0

Je ne supporte pas les navigateurs avec une précision de 1ms. Il semble être 15 ms pour la plupart des navigateurs :) –

+0

@Vivin, noté dans le premier paragraphe. J'ai laissé 1 dans le deuxième paragraphe pour essayer d'éviter la confusion pour le PO. – JaredPar

+0

Ah, je n'ai pas vu ça quand j'ai commenté. Je n'ai pas rechargé la page. Ma faute! –

1

Non, JavaScript n'a pas de multithreading, du moins pas pour le moment.

Veuillez lire this answer pour voir comment fonctionne setInterval.

8

Non, Javascript est monothread. Lorsque vous exécutez setInterval ou setTimeout, un événement est généré qui est ensuite ajouté à la file d'attente d'exécution du navigateur. Donc, même si vous ne pouvez pas garantir que le code lui-même exécutera exactement lorsque vous le souhaitez, vous pouvez être sûr que l'événement sera généré chaque fois qu'il est censé être généré. Donc, dans ce cas, vous avez 12 événements générés très proches les uns des autres. Je remarque que vous avez utilisé 1 comme valeur d'intervalle. Toutefois, les valeurs minimales dans la plupart des navigateurs sont autour de 15 (voir here pour plus d'informations.) Le navigateur parcourt les événements dans l'ordre dans lequel ils se trouvent dans la file d'attente d'exécution (dans setInterval, les événements tentent de rattraper le retard. répond que Marcel a lié à, pour plus de détails).Cela signifie que dans le premier scénario un événement est généré toutes les 15 millisecondes environ. Donc le compteur est incrémenté plus lentement. Mais dans le second cas, vous avez douze événements qui sont lancés assez près les uns des autres toutes les 15 millisecondes, et ainsi le compteur s'incrémente beaucoup plus rapidement.

1

Le code que vous avez publié ne fonctionne pas, voici le code corrigé:

var i=0; 
setInterval(foo,1); 

function foo() { 
    i+=1; 
    if ($("#foodiv").text()==i) { 
    //we detected a doubled value (parallel execution) 
    $("#repdiv").append("[repetition on "+i+"]"); 
    } 
    $("#foodiv").html(i); 
} 

Si vous regardez les performances du processeur tandis que le code fonctionne, vous voyez que cela fonctionne à peine du tout, ce qui signifie que le taux inférieur n'est pas dû au fait que le code est occupé. Il ne sera tout simplement pas déclencher l'intervalle aussi souvent que vous avez demandé.

(Si vous commencez à douze intervalles, la charge est encore à peine perceptible. J'ai commencé à 200 intervalles avant d'obtenir une charge près de 100% sur l'un des noyaux.)

Le navigateur utilise une sorte d'horloge pour déterminer quels intervalles doivent être déclenchés, et cette horloge a généralement une résolution inférieure à millisecondes. Donc, l'intervalle ne tirera pas de nouveau jusqu'à la prochaine marque d'horloge, qui dans votre cas semble être à environ 15 ms d'intervalle.