问题
I want to execute a thread periodically to check if some file is ready for uploaded and upload it as soon as it is ready then stop the thread immediately. Also, if a long time has passed I want to stop the thread regardless the file not being ready, but can't do it inside the run method itself.
final ScheduledFuture<?> fileUploadedFuture = scheduler.scheduleAtFixedRate(() -> {
try {
if (fileReady("xyz.txt")) {
uploadFile("xyz.txt")
//cancel fileUploadedFuture and fileUploadedFutureCanceller
}
} catch (Exception e) {
throw new ServiceException(e);
}
}, 0, delay, TimeUnit.SECONDS);
final ScheduledFuture<?> fileUploadedFutureCanceller = scheduler.schedule(() -> {
fileUploadedFuture.cancel(true);
}, 60, TimeUnit.SECONDS);
}
回答1:
How about using a ScheduledThreadPoolExecutor?
public class TestExecutor {
private static ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
private static class PushFile implements Runnable {
@Override
public void run() {
if (new File("test.txt").exists()) {
System.out.println("found it!");
exec.shutdown();
} else {
System.out.println("waiting");
}
}
}
private static class ShutMeDown implements Runnable {
@Override
public void run() {
System.out.println("timeout");
exec.shutdown();
}
}
public static void main(String[] args) {
exec.scheduleWithFixedDelay(new PushFile(), 0, 1, TimeUnit.SECONDS);
exec.scheduleWithFixedDelay(new ShutMeDown(), 10, 1, TimeUnit.SECONDS);
}
}
回答2:
@laughing buddha suggested a watcher. It's probably more resource-efficient than my first suggestion, but I'm not entirely sure it's the right solution in this case, because you're still parking a thread. Nevertheless, I coded a test, and it's short and easy to read, so you may as well have the code:
public class TestWatchService {
public static void main(String[] args) throws IOException, InterruptedException {
WatchService watcher = FileSystems.getDefault().newWatchService();
Path file = Paths.get(".");
WatchKey key = file.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
List<WatchEvent<?>> events = new ArrayList<>();
for (boolean done = false; ! done; events = key.pollEvents()) {
if (events.size()==0) {
System.out.println("waiting");
Thread.sleep(2000L);
} else {
System.out.println("got it!");
done = true;
}
}
}
}
来源:https://stackoverflow.com/questions/44006905/execute-thread-periodically-and-stop-it-after-condition-is-met-or-time-is-over