2010-10-27 33 views
5

Khi sử dụng javascript, tôi nhận thấy điều này. Bạn có thể sử dụngHành vi này của setInterval có ngụ ý hành vi đa luồng trong Javascript không?

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)); 
} 

nhưng khi tôi đọc và tự thử thời gian không phải là 1ms, ít nhất là 10ms hoặc gì đó. Trong thực tế sau 10 giây, tôi có một giá trị của tôi khoảng 2300/2400, và không phải là 10000 như mong đợi.

Đây là yếu tố thời gian tối thiểu có thể cho quy trình ??? Chắc chắn là không. Nếu tôi thử điều này:

<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> 

Bộ đếm sẽ rất nhanh và sau 10 giây, tôi có giá trị là 12000 !!!! Đó là cho tôi là không thể giải thích, bởi vì cuộc gọi không được thực hiện song song (hoặc ít nhất chúng tôi có thể có một số giá trị đọc gấp đôi của tôi cho các cuộc gọi khác nhau, tìm trong div repdiv).

Ai đó có thể giải thích cho tôi điều đó không? Tôi biết CPU là rất nhấn mạnh bởi tất cả những cuộc gọi, nhưng ít nhất nó tăng tốc độ những điều đáng ngạc nhiên.

Tôi đọc tất cả câu trả lời của bạn và các nhiệm vụ khác trong diễn đàn và họ đã xác nhận suy nghĩ của tôi. Nhưng câu hỏi thực sự là tại sao! Tại sao họ đặt giới hạn thành 15ms khi tôi có thể thực hiện nhiều cuộc gọi tuần tự có thời gian thấp hơn nhiều? Tôi chắc chắn rằng hệ thống gọi lại nhiều này không phải là thực hành tốt, nhưng tôi có thể làm điều đó, và tôi có khả năng có thể bão hòa tải CPU.

+5

Tôi không thấy mã này hoạt động như thế nào, khoảng thời gian thiết lập lấy hàm làm đối số đầu tiên, không phải foo(), nó sẽ phải giống như setInterval (foo, 1). Ngoài ra bạn đang thiếu một số kết thúc) sau khi của bạn nếu và nối thêm –

+0

Ngoài ra, giả sử mã là chính xác, các giá trị có vẻ sai. Với 12 giờ, bộ đếm sẽ chỉ nhanh hơn 12 lần, vì vậy 600 sẽ trở thành 7200, không phải 150000. Một cái gì đó nói với tôi rằng đây không phải là mã mà OP đã kiểm tra. – casablanca

+0

bạn nói đúng, tôi đã chỉnh sửa mã nhiều lần và tạo lại nó ở nhà, nhưng khái niệm này không thay đổi. Tôi sẽ lặp lại những thứ như tôi đã làm một cách hiệu quả. Ngoài ra nếu bạn nhận thấy tôi bỏ qua mã html, và điều đó làm cho mọi thứ tồi tệ nhất nếu bạn cố gắng này như nó được. – mizar

Trả lời

0

Giá trị thứ hai được chuyển cho phương thức setInterval thực sự là giá trị tối thiểu. Mặc dù 1 đại diện cho 1 mili giây và không chắc rằng hầu hết các trình duyệt sẽ cung cấp cho bạn chính xác thời gian chờ này. Một câu trả lời khác nói rằng nó có nhiều khả năng là khoảng 15 mili giây.

Mặc dù vậy, mục thứ hai là giá trị tối thiểu adequetely giải thích mẫu đầu tiên.

Mẫu thứ hai cũng được giải thích bởi hành vi này. Mỗi phương thức setInterval bạn gọi sẽ đăng ký cuộc gọi hoàn toàn riêng biệt. Mỗi người có tối thiểu 1 nhưng không phụ thuộc lẫn nhau. Vì vậy, nó hoàn toàn hợp lệ cho tất cả chúng để bắn trong cùng một khoảng thời gian 1 mili giây (miễn là mỗi bản thân nó đợi 1 mili giây trước khi kích hoạt lại).

+0

Tôi không có trình duyệt nào hỗ trợ độ chính xác 1ms. Có vẻ như là 15ms đối với hầu hết các trình duyệt :) –

+0

@Vivin, được ghi chú trong đoạn đầu tiên. Tôi để lại 1 trong đoạn thứ hai để thử và tránh nhầm lẫn cho OP. – JaredPar

+0

Ah, không thấy điều đó khi tôi bình luận. Không tải lại trang. Lỗi của tôi! –

1

Không, JavaScript không có đa luồng, ít nhất là không phải tại thời điểm này.

Vui lòng đọc this answer để xem cách hoạt động của setInterval.

8

Không, Javascript là một chuỗi duy nhất. Khi bạn chạy setInterval hoặc setTimeout, sự kiện được tạo sau đó được thêm vào hàng đợi thực thi của trình duyệt. Vì vậy, trong khi bạn không thể đảm bảo rằng chính mã sẽ chạy chính xác khi bạn muốn nó chạy, bạn có thể chắc chắn rằng sự kiện sẽ được tạo ra mỗi khi nó được cho là được tạo ra. Vì vậy, trong trường hợp này, bạn có 12 sự kiện đang được tạo ra thực sự gần nhau. Tôi nhận thấy rằng bạn đã sử dụng 1 làm giá trị khoảng thời gian. Tuy nhiên, giá trị tối thiểu trong hầu hết các trình duyệt là khoảng 15 (xem here để biết thêm thông tin.) Trình duyệt sẽ chạy qua các sự kiện theo thứ tự chúng nằm trong hàng đợi thực hiện (trong setInterval, các sự kiện cố gắng bắt kịp. trả lời rằng Marcel liên kết, để biết thêm chi tiết).

Điều này có nghĩa là trong trường hợp đầu tiên bạn có một sự kiện được tạo mỗi 15 hoặc hơn một phần nghìn giây. Vì vậy, truy cập được tăng lên chậm hơn. Nhưng trong trường hợp thứ hai, bạn có mười hai sự kiện được kích hoạt khá gần nhau mỗi 15 hoặc hơn một phần nghìn giây và vì vậy bộ đếm tăng nhanh hơn nhiều.

1

Các mã mà bạn đăng tải không chạy, đây là mã sửa:

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); 
} 

Nếu bạn nhìn vào hiệu suất CPU trong khi mã chạy, bạn sẽ thấy rằng nó hầu như không làm việc ở tất cả, điều đó có nghĩa rằng tỷ lệ thấp hơn không phải do mã đang bận. Nó chỉ đơn giản là sẽ không cháy khoảng thời gian thường xuyên như bạn yêu cầu.

(Nếu bạn bắt đầu mười hai khoảng thời gian, tải trọng vẫn là hầu như không đáng kể. Tôi bắt đầu 200 chu kỳ trước khi nhận được một tải gần 100% vào một trong các lõi.)

Trình duyệt sử dụng một số loại đồng hồ để xác định khoảng thời gian nào sẽ được kích hoạt và đồng hồ đó thường có độ phân giải thấp hơn mili giây. Vì vậy, khoảng thời gian sẽ không cháy một lần nữa cho đến khi đồng hồ đánh dấu tiếp theo, mà trong trường hợp của bạn dường như là khoảng 15 ms ngoài.