Java定时器只触发一次(仅服务器问题)



好吧,这是一个奇怪的问题,似乎不是编码问题。我在家用电脑和服务器电脑上都安装了Intellij(两者都运行windows pro)。我把它放在一边。两者都打开了Intellij,并且都具有相同的复制粘贴代码。在我的家用电脑上,这个代码运行得很好,每60秒就会启动一次。但在服务器计算机上,它会启动一次,不会再启动。我把它装进一个罐子里,然后运行罐子,同样的东西,它运行一次,再也不会运行了。这是代码。

public class BackupTask extends TimerTask {
    private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH_mm_ss");
        }
    };
    public void run() {
        try {
            File src = new File("C:\Users\justi\Desktop\Server\Saved");
            File dest = new File("\\READYSHARE\USB_Storage\Backups\" + df.get().format(Calendar.getInstance().getTime()));
            if(!dest.exists()){
                dest.mkdir();
            }
            copyFolder(src, dest);
        }catch(Exception e){
            System.out.println("Error: " + e);
        }
    }
    public static void copyFolder(File src, File dest)
            throws IOException{
        if(src.isDirectory()){
            //if directory not exists, create it
            if(!dest.exists()){
                dest.mkdir();
            }
            //list all the directory contents
            String files[] = src.list();
            for (String file : files) {
                //construct the src and dest file structure
                File srcFile = new File(src, file);
                File destFile = new File(dest, file);
                //recursive copy
                copyFolder(srcFile,destFile);
            }
        }else{
            //if file, then copy it
            //Use bytes stream to support all file types
            InputStream in = new FileInputStream(src);
            OutputStream out = new FileOutputStream(dest);
            byte[] buffer = new byte[1024];
            int length;
            //copy the file content in bytes
            while ((length = in.read(buffer)) > 0){
                out.write(buffer, 0, length);
            }
            in.close();
            out.close();
        }
    }
}

AutoBackup.java

public class AutoBackup {
//    Timer timer;
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private final int TIME_BETWEEN_SAVES = 60;
    public AutoBackup(){
        final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(new BackupTask(), 10, TIME_BETWEEN_SAVES, TimeUnit.SECONDS);
    }
    public static void main(String[] args) {
        new AutoBackup();
//        Timer timer = new Timer();
//        timer.schedule(new BackupTask(), 1000, 60 * 1000);
    }
}

这个程序只是在预定的时间间隔内从一个位置复制粘贴到另一个位置。我也试过以管理员的身份运行Intellij,但我对为什么会发生这种情况一无所知。服务器计算机有一个核心i5-4690k,Micro ITX千兆字节超耐用的GA-H97N-WIFI H97主板与16 gigs的ram。如果还有其他有用的信息,请告诉我。

您所描述的非常奇怪,但我提出了一种情况,即您的代码可能会失败。让我详细描述一下。您首先创建一个线程池大小为1:的新调度执行器

Executors.newScheduledThreadPool(1);

这个单独的线程将用于执行您的可运行程序。然后你安排以固定速率运行,10秒后首先运行,然后每60秒运行一次:

scheduler.scheduleAtFixedRate(new BackupTask(), 10, 60, TimeUnit.SECONDS);

现在,因为executor中只有一个线程可以运行可运行程序,所以当BackupTask由于任何原因挂起,或者执行时间更长时,下一次执行将延迟到第一次执行完成为止。您正在进行网络备份,因此问题可能与网络有关。例如,执行close()可能会导致代码等待网络超时(取决于超时值的长度),或者在相同的场景中执行write(..)。

我建议在代码中放入一些调试语句(请参阅下面的代码)。我知道这可能会在应用程序控制台中产生一些垃圾,但如果你不想远程调试,这可能是找出代码错误的唯一方法。

public static void copyFolder(File src, File dest) throws IOException{
    if (src.isDirectory()) {
        //if directory not exists, create it
        if(!dest.exists()){
            System.out.println("Creating directory " + dest);
            dest.mkdir();
            System.out.println("Created directory ");
        }
        for (String file : src.list()) {
            File srcFile = new File(src, file);
            File destFile = new File(dest, file);
            System.out.println("Copying " + srcFile + " to " + destFile);
            copyFolder(srcFile,destFile);
            System.out.println("Copied " + srcFile + " to " + destFile);
        }
    }else{
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dest);
        byte[] buffer = new byte[1024];
        System.out.println("Writing file " + src + " to " + dest);
        int length;
        //copy the file content in bytes
        while ((length = in.read(buffer)) > 0){
            out.write(buffer, 0, length);
        }
        System.out.println("Closing file " + src);
        in.close();
        System.out.println("Closing file " + dest);
        out.close();
        System.out.println("Writing file " + src + " to " + dest + " is done");
    }
}

此外,我对你的代码的几点评论:

您的BackupTask会延长TimerTask。这是不必要的。实现Runnable就足够了。

当您从流中写入/读取时,您应该始终确保关闭finally部分中的资源,或者使用try with resources(从Java 7开始)。否则,文件可能会永远打开。

InputStream in = null;
OutputStream out = null;
byte[] buffer = new byte[1024];
int length;
try {
  in = new FileInputStream(src);
  out = new FileOutputStream(dest);
  while ((length = in.read(buffer)) > 0) {
    out.write(buffer, 0, length);
  }
} finally {
  if (in != null) {
    try {
      in.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  if (out != null) {
    try {
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

最新更新