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

时间:2016-01-04 05:08:24

标签: java windows server hardware

好的,这是一个奇怪的,它似乎不是一个编码问题。我在我的家用电脑和服务器电脑上安装了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 Gigabyte超耐用GA-H97N-WIFI H97主板,有16演出的ram。如果有任何其他信息可以帮助我,请告诉我。

1 个答案:

答案 0 :(得分:2)

你所描述的内容非常奇怪,但是当你的代码可能失败时,我出现了一个案例。让我详细描述一下。首先使用线程池大小= 1创建新的预定执行程序:

Executors.newScheduledThreadPool(1);

这个单线程将用于执行你的runnables。然后你安排固定费率的runnable,10秒后先运行,然后每60秒运行一次:

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

现在,因为执行程序中只有一个线程可以运行runnables,当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();
    }
  }
}