我有一个包含三行的测试文件,每行以一个以秒为单位的时间戳开头。我读了这个时间戳,在此基础上我安排了一个新的计时器 为每个时间戳阅读。为什么当我运行在下面提到的方法“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
答案 0 :(得分:3)
我怀疑它内部的for循环和计数器以及你创建线程的新实例的方式。 我会这样做。
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循环中的计数器将始终获得其最大值wihch将应用于所有Timertasks。换句话说,如果yu有一个5次迭代的循环,计数器将根据计数器的初始化方式获得其最大值,然后这个计数器值用你来解析文件中的特定数据,这意味着你得到了值frm最后一行然后将其应用于timerTask
答案 1 :(得分:1)
我会以currentLine
不同的方式解决比赛:
for (int i = 1; i <= logfile.getTotalLines(); i++) {
t = new Thread(new ThreadFile(i), "logFile_Thread_" + i);
t.start();
}
因此定义ThreadFile
:
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());
}
}
这样,当您创建runnable时,它已经知道要访问哪一行,并且无法访问 common 变量而无需同步。
logfile
可能仍然存在某种问题,因为它也是常见的而且不是同步的,但如果我们所做的只是读取并且读取不涉及更新其状态,那么它应该是行。