timerSchedule не подчиняется установленному таймеру запуска?
У меня есть тестовый файл с тремя строками, каждая строка начинается с отметки времени в секундах. Я читаю этот штамп времени и на его основе планирую новый таймер за каждый прочитанный штамп времени. Почему, когда я запускаю потоки, созданные в методе "processFile", упомянутом ниже, консоль отображает выходные данные трех таймеров одновременно? Я ожидал увидеть выход каждого таймера, разделенный несколькими секундами задержки между ними, как отметку времени каждой из трех строк, которые я читал из файла 2 секунды, 15 секунд и 7 секунд соответственно? когда я запускаю программу, через несколько секунд я получаю ниже" системное время " вывода все сразу без задержки разделяют их, несмотря на то, что временная метка, считываемая из файла, отличается!
Пожалуйста, дайте мне знать, почему это происходит и как это решить.//this method is being called on a worker thread
private static void processFile(File dataFile) throws IOException {
// TODO Auto-generated method stub
System.out.println(WORKER_THREAD + " started.");
logfile = new MeasurementFile(dataFile, MeasurementFile.ENCODING_UTF_8);
System.out.println("Total lines in the file: " + logfile.getTotalLines());
System.out.println("#Parameters/line: " + logfile.getFileHash().get(logfile.getTotalLines()).getFullParameters().length);
System.out.println("Time Stamp in Seconds: " + logfile.getFileHash().get(logfile.getTotalLines()).getTimeStampInSec());
timer = new Timer();
for (int i = 1; i <= logfile.getTotalLines(); i++) {
++currentLine;
t = new Thread(new threadFile(), "logFile_Thread_" + i);
t.start();
}
}
static class threadFile implements Runnable {
public void run() {
timer.schedule(new timedTask(), (long) logfile.getFileHash().get(currentLine).getTimeStampInMilli());
}
}
static class timedTask extends TimerTask {
@Override
public void run() {
// TODO Auto-generated method stub
long nanoTimer = System.nanoTime();
//long milliTimer = System.currentTimeMillis();
System.out.println("systemTime(ns): " + nanoTimer);
}
}
Вывод :
file processing thread started.
Total lines in the file: 3
#Parameters/line: 9
Time Stamp in Seconds: 7.0
systemTime(ns): 4882255697670
systemTime(ns): 4882255928644
systemTime(ns): 4882255985104
2 ответа:
Я подозреваю, что цикл for и счетчик внутри него и способ, которым вы создаете экземпляр потока n ew. Я бы сделала это таким образом.
for (int i = 1; i <= logfile.getTotalLines(); i++) { t = new Thread(threadFile, "logFile_Thread_" + i); t.start(); } static Runnable threadFile = new Runnable() { public void run() { // TODO Auto-generated method stub ++currentLine; timer.schedule(new timedTask(), (long) logfile.getFileHash().get(currentLine).getTimeStampInMilli()); } };
Потому что счетчик в for-цикле, получит всегда свое максимальное значение, которое будет применено ко всем Таймерным задачам. другими словами, если у вас есть цикл для 5 итераций, счетчик получит свое максимальное значение в зависимости от того, как счетчик был инициализирован, а затем эти значения счетчика вы используете для анализа конкретных данных из вашего файла, что означает вы всегда получаете значение frm в последней строке, а затем применяете его к timerTask
Я бы решил гонку на
currentLine
по-другому:for (int i = 1; i <= logfile.getTotalLines(); i++) { t = new Thread(new ThreadFile(i), "logFile_Thread_" + i); t.start(); }
Определяя
ThreadFile
таким образом:Таким образом, когда вы создаете runnable, он уже знает, к какой строке обращаться, и нет доступа к общей переменной и нет необходимости в синхронизации.static class ThreadFile implements Runnable { private int lineToProcess; public ThreadFile( int lineToProcess ) { super(); this.lineToProcess = lineToProcess; } public void run() { timer.schedule(new timedTask(), (long) logfile.getFileHash().get(lineToProcess).getTimeStampInMilli()); } }
Все еще может быть какая-то проблема с
logfile
, так как он тоже общий и не синхронизирован, но если все, что мы делаем, это читаем из него, и чтение не включает в себя обновление его состояния, оно должно быть в порядке.