timerSchedule不服从启动计时器设置?

时间:2014-12-05 09:11:24

标签: java timer timertask

我有一个包含三行的测试文件,每行以一个以秒为单位的时间戳开头。我读了这个时间戳,在此基础上我安排了一个新的计时器 为每个时间戳阅读。为什么当我运行在下面提到的方法“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 个答案:

答案 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可能仍然存在某种问题,因为它也是常见的而且不是同步的,但如果我们所做的只是读取并且读取不涉及更新其状态,那么它应该是行。