Tôi có vấn đề kỳ lạ - Tôi hy vọng một người nào đó có thể giải thích cho tôi điều gì đang xảy ra và cách giải quyết có thể xảy ra. Tôi đang thực hiện một lõi Z80 trong Java, và cố gắng làm chậm nó xuống, bằng cách sử dụng một đối tượng java.util.Timer trong một luồng riêng biệt.Độ chính xác thời gian Java trên Windows XP so với Windows 7
Thiết lập cơ bản là tôi có một luồng chạy vòng lặp thực thi, 50 lần mỗi giây. Trong vòng lặp thực hiện này, tuy nhiên nhiều chu kỳ được thực hiện, và sau đó wait() được gọi. Chủ đề Timer bên ngoài sẽ gọi notifyAll() trên đối tượng Z80 sau mỗi 20ms, mô phỏng tần số xung nhịp hệ thống PAL Sega Master là 3,54 MHz (ish).
Phương pháp tôi đã mô tả ở trên hoạt động hoàn hảo trên Windows 7 (đã thử hai máy) nhưng tôi cũng đã thử hai máy Windows XP và cả hai, đối tượng Bộ hẹn giờ dường như quá tải khoảng 50%. Điều này có nghĩa là một giây của thời gian mô phỏng thực sự mất khoảng 1,5 giây hoặc lâu hơn trên máy tính Windows XP.
Tôi đã thử sử dụng Thread.sleep() thay vì đối tượng Timer, nhưng điều này có cùng tác dụng chính xác. Tôi nhận ra độ chi tiết của thời gian trong hầu hết các hệ điều hành không tốt hơn 1ms, nhưng tôi có thể đặt lên với 999ms hoặc 1001ms thay vì 1000ms. Những gì tôi không thể đưa ra là 1562ms - Tôi chỉ không hiểu tại sao phương pháp của tôi hoạt động OK trên phiên bản Windows mới hơn, nhưng không phải là phiên bản cũ hơn - Tôi đã điều tra các khoảng thời gian ngắt quãng, v.v. đã phát triển cách giải quyết.
Có ai vui lòng cho tôi biết nguyên nhân của vấn đề này và giải pháp được đề xuất không? Cảm ơn nhiều.
Cập nhật: Đây là mã đầy đủ cho một ứng dụng nhỏ tôi đã xây dựng để hiển thị cùng một vấn đề:
import java.util.Timer;
import java.util.TimerTask;
public class WorkThread extends Thread
{
private Timer timerThread;
private WakeUpTask timerTask;
public WorkThread()
{
timerThread = new Timer();
timerTask = new WakeUpTask(this);
}
public void run()
{
timerThread.schedule(timerTask, 0, 20);
while (true)
{
long startTime = System.nanoTime();
for (int i = 0; i < 50; i++)
{
int a = 1 + 1;
goToSleep();
}
long timeTaken = (System.nanoTime() - startTime)/1000000;
System.out.println("Time taken this loop: " + timeTaken + " milliseconds");
}
}
synchronized public void goToSleep()
{
try
{
wait();
}
catch (InterruptedException e)
{
System.exit(0);
}
}
synchronized public void wakeUp()
{
notifyAll();
}
private class WakeUpTask extends TimerTask
{
private WorkThread w;
public WakeUpTask(WorkThread t)
{
w = t;
}
public void run()
{
w.wakeUp();
}
}
}
Tất cả các lớp học chính không được tạo ra và bắt đầu một trong những chủ đề người lao động. Trên Windows 7, mã này tạo ra thời gian khoảng 999ms - 1000ms, điều này hoàn toàn ổn. Chạy cùng một lọ trên Windows XP tuy nhiên tạo ra một khoảng thời gian khoảng 1562ms - 1566ms, và đây là trên hai máy XP riêng biệt mà tôi đã thử nghiệm này. Tất cả chúng đều đang chạy bản cập nhật Java 6 27.
Tôi thấy vấn đề này đang xảy ra vì Timer đang ngủ 20ms (một giá trị nhỏ) - nếu tôi bung tất cả các vòng lặp thực hiện trong một giây chờ đợi chờ đợi() - thông báo choAll() chu kỳ, điều này tạo ra kết quả chính xác - Tôi chắc chắn rằng những người nhìn thấy những gì tôi đang cố gắng thực hiện (mô phỏng hệ thống Sega Master ở 50fps) sẽ thấy đây không phải là giải pháp. thời gian đáp ứng tương tác, bỏ qua 49 của mỗi 50. Như tôi đã nói, Win7 đối phó tốt với điều này. Xin lỗi nếu mã của tôi là :-(quá lớn
Câu hỏi thú vị. Bạn có thể cung cấp đoạn mã khép kín thể hiện hành vi này không? – NPE
Tôi có thể cung cấp cho bạn mã nguồn của Bộ hẹn giờ nếu bạn thích? Tôi muốn cung cấp cho bạn rất nhiều nhưng lõi Z80 đang hình thành khá nặng ;-) – PhilPotter1987
@aix * "đoạn mã khép kín" * Mã tự chứa có thể ngắn, nhưng không thể (theo định nghĩa) là [ đoạn mã] (http://en.wikipedia.org/wiki/Snippet_%28programming%29). Tôi khuyên bạn nên đăng một [SSCCE] (http://pscode.org/sscce.html). –