我正在尋找在Java中實現一種產生任務的機制。這項任務實際上並不相關,它可以通過一個線程或新進程來完成。帶有重試和故障轉移的Java線程/進程
我真正需要的是這樣的:
- 任務可設置爲重試了N次
- 如果一些討厭的任務範圍內發生的,產生它的母公司是受保護的
- 兩者的應該從上面抽象出來
有沒有人知道任何可以在Java中做到的框架?
我正在尋找在Java中實現一種產生任務的機制。這項任務實際上並不相關,它可以通過一個線程或新進程來完成。帶有重試和故障轉移的Java線程/進程
我真正需要的是這樣的:
有沒有人知道任何可以在Java中做到的框架?
如果一些討厭的任務範圍內發生的,產生它的母公司是受保護的
所以我猜你有3種選擇。
是在另一個進程中運行任務。看到類似Get Java Runtime Process running in background。我不知道一個可以幫助解決這個問題的框架。這個框架沒有太多的代碼可以節省你的代碼。
在同一個JVM上的另一個線程中運行。見下文。
在另一個服務器上的另一個進程中運行。您將不得不編寫客戶端/服務器或使用Web框架或RMI執行遠程處理。我不知道任何框架會自動爲你做這件事。
就在同一JVM中運行它而言,我根本不使用框架。我只是在適當的異常處理循環中運行任務:
for (int i = 0; i < retries; i++) {
try {
doTask();
} catch (Throwable t) {
// log the throwable here
}
}
看起來像一個框架只是太複雜了。如果任務耗盡內存,那麼在另一個線程中運行它將無濟於事,您將不得不產生另一個進程來處理任務。
如果你需要它在後臺運行,那麼@assyliaas關於使用線程池的最初答案是正確的選擇。
事實上 - 我被冠軍奪走了! – assylias
這並不能解決有關保護的問題。什麼是線程去OOM? – imrichardcole
Np老兄。如果他需要它在背景@assylias中運行,你會發現它。 – Gray
我一直在想這個問題已經有一段時間了,終於有了一些你認爲有用的東西。
我們的小「框架」的第一部分是Task
接口:
public interface Task {
void work();
void stop();
}
實現這一點,我們可以建立我們WorkTask
:
public class WorkTask implements Task {
@Override
public void work() {
// Do something useful...
// might throw SomethingNastyHappenedException
}
@Override
public void stop() {
// implement as needed e.g. to break inner loops
}
}
爲了符合您的要求,以便能夠重試這我們創建一個Wrapper
類:
public class RetryingTaskWrapper implements Task {
private Task wrappedTask;
private int maxTries;
private boolean running = false;
public RetryingTaskWrapper(Task wrappedTask, int maxTries) {
this.wrappedTask = wrappedTask;
this.maxTries = maxTries;
}
@Override
public void work() {
running = true;
boolean success = false;
int tries = 0;
while (running && !success && tries < maxTries) {
try {
wrappedTask.work();
success = true;
} catch (SomethingNastyHappenedException e) {
// something nasty happed so retry
tries++;
} catch (Exception e) {
// something even worse happened -> end
running = false;
}
}
running = false;
}
@Override
public void stop() {
running = false;
wrappedTask.stop();
}
}
最後,我們需要一些東西來運行我們的任務...
public class TaskRunner implements Runnable {
private Thread thread;
private Task task;
private boolean running = false;
public TaskRunner(Task task) {
this.task = task;
}
public synchronized void start() {
if (thread != null) {
return;
}
thread = new Thread(this);
thread.start();
}
@Override
public void run() {
running = true;
if (task != null) {
try {
task.work();
} catch (Exception e) {
// log your exception
}
}
thread = null;
running = false;
}
public void stop() {
if (running) {
if (task != null) {
task.stop();
}
if (thread != null) {
thread.interrupt();
}
}
}
}
現在,我們有我們需要的就是建立一個TaskRunner並啓動它:如果您要在不重試運行WorkTask
一次
WorkTask workTask = new WorkTask();
TaskRunner runner = new TaskRunner(new RetryingTaskWrapper(workTask, 5));
runner.start();
,這也是可能的:
WorkTask workTask = new WorkTask();
TaskRunner runner = new TaskRunner(workTask);
runner.start();
如果你想要你甚至可以在無限循環中運行你的WorkTask
而不必改變你自己的WorkTask
。所有你需要的是創建另一個包裝
public class InfiniteLoopTaskWrapper implements Task {
private Task wrappedTask;
private boolean running = false;
public InfiniteLoopTaskWrapper(Task wrappedTask) {
this.wrappedTask = wrappedTask;
}
@Override
public void work() {
running = true;
while (running) {
try {
wrappedTask.work();
} catch (SomethingNastyHappenedException e) {
// log that something nasty happened
} catch (Exception e) {
// something even worse happened -> end
running = false;
}
}
}
@Override
public void stop() {
running = false;
wrappedTask.stop();
}
}
並運行它...
WorkTask workTask = new WorkTask();
TaskRunner runner = new TaskRunner(new InfiniteLoopTaskWrapper(workTask));
runner.start();
聽起來像你正在尋找[線程](http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html)。他們爲你做這一切。也許是一個[定時器](http://docs.oracle.com/javase/6/docs/api/javax/swing/Timer.html)。 – OldCurmudgeon
我認爲阿卡會解決這個問題。如果有人可以確認,很樂意回答我自己的問題嗎? – imrichardcole