我想創建一個定期運行某個(可運行)的類,但可以在需要時喚醒它。如果我可以封裝整個事情,我想公開以下方法:創建一個在定時器上運行的java線程,但可以在任何時候喚醒
public class SomeService implements Runnable {
public run() {
// the code to run at every interval
}
public static void start() { }
public static void wakeup() { }
public static void shutdown() { }
}
不知何故,我已經得到了這麼多。但我不確定這是否是正確的方法。
public class SomeService implements Runnable {
private static SomeService service;
private static Thread thread;
static {
start();
}
private boolean running = true;
private SomeService() {
}
public void run() {
while (running) {
try {
// do what needs to be done
// perhaps peeking at a blocking queue
// or checking for records in a database
// trying to be independent of the communication
System.out.println("what needs to be done");
// wait for 15 seconds or until notify
synchronized (thread) {
try {
thread.wait(15000);
} catch (InterruptedException e) {
System.out.println("interrupted");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static void start() {
System.out.println("start");
service = new SomeService();
thread = new Thread(service);
thread.setDaemon(true);
thread.start();
}
public static void wakeup() {
synchronized (thread) {
thread.notify();
}
}
public static void shutdown() {
synchronized (thread) {
service.running = false;
thread.interrupt();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("shutdown");
}
public static void main(String[] args) throws IOException {
SomeService.wakeup();
System.in.read();
SomeService.wakeup();
System.in.read();
SomeService.shutdown();
}
}
我擔心變量應該被聲明爲volatile。並且擔心thread.isInterrupted()
需要檢查「需要完成的部分」。這看起來是不是正確的方法?我應該把它翻譯成執行者嗎?我該如何強制執行預定的執行者?
編輯
與執行試驗之後,似乎這種做法似乎是合理的。你怎麼看?
public class SomeExecutorService implements Runnable {
private static final SomeExecutorService runner
= new SomeExecutorService();
private static final ScheduledExecutorService executor
= Executors.newSingleThreadScheduledExecutor();
// properties
ScheduledFuture<?> scheduled = null;
// constructors
private SomeExecutorService() {
}
// methods
public void schedule(int seconds) {
scheduled = executor.schedule(runner, seconds, TimeUnit.SECONDS);
}
public void force() {
if (scheduled.cancel(false)) {
schedule(0);
}
}
public void run() {
try {
_logger.trace("doing what is needed");
} catch (Exception e) {
_logger.error("unexpected exception", e);
} finally {
schedule(DELAY_SECONDS);
}
}
// static methods
public static void initialize() {
runner.schedule(0);
}
public static void wakeup() {
runner.force();
}
public static void destroy() {
executor.shutdownNow();
}
}
如我所知,製作所有靜態方法是一個不好的做法。你爲什麼不只保留'main()''static'並且創建一個實例'service = new SomeService();' – alaster
@alaster我在想這會封裝這個問題,因爲我不需要保留跟蹤創建的「服務」。通過靜態聲明,我可以使用'SomeService.wakeup()'對其進行演示,並使用'SomeService.shutdown()'完成它。由於我只能有一個跑步......這似乎是一個好方法。 – rmarimon