Java 计时器仅触发一次(仅服务器问题)
Java Timer only fire once (server only issue)
好的,这是一个奇怪的问题,它似乎不是编码问题。我在家用电脑和服务器电脑上都安装了 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 GB 内存。如果有任何其他信息可以帮助,请告诉我。
你描述的很奇怪,但我想出了一个案例,你的代码可能会失败。让我详细描述一下。您首先创建线程池大小为 1 的新计划执行程序:
Executors.newScheduledThreadPool(1);
这个单线程将用于执行您的 运行nables。然后你安排 运行nable 以固定速率,首先在 10 秒后 运行,然后每 60 秒:
scheduler.scheduleAtFixedRate(new BackupTask(), 10, 60, TimeUnit.SECONDS);
现在,因为您在执行器中只有一个线程可以 运行 您的 运行nables,当您的 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就够了。
当你从流中 write/read 时,你应该始终确保在 finally 部分关闭你的资源,或者使用资源尝试(从 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();
}
}
}
好的,这是一个奇怪的问题,它似乎不是编码问题。我在家用电脑和服务器电脑上都安装了 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 GB 内存。如果有任何其他信息可以帮助,请告诉我。
你描述的很奇怪,但我想出了一个案例,你的代码可能会失败。让我详细描述一下。您首先创建线程池大小为 1 的新计划执行程序:
Executors.newScheduledThreadPool(1);
这个单线程将用于执行您的 运行nables。然后你安排 运行nable 以固定速率,首先在 10 秒后 运行,然后每 60 秒:
scheduler.scheduleAtFixedRate(new BackupTask(), 10, 60, TimeUnit.SECONDS);
现在,因为您在执行器中只有一个线程可以 运行 您的 运行nables,当您的 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就够了。
当你从流中 write/read 时,你应该始终确保在 finally 部分关闭你的资源,或者使用资源尝试(从 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();
}
}
}