我希望在 Java 中实现一种机制,在其中产生一个任务。任务所做的实际上与这里无关,它可以通过线程或新进程来完成。
我真正需要的是:
- 任务可设置重试N次
- 如果任务中发生了令人讨厌的事情,产生它的父级将受到保护
- 以上两个都应该从我身上抽象出来
有谁知道在 Java 中可以做到这一点的任何框架?
我希望在 Java 中实现一种机制,在其中产生一个任务。任务所做的实际上与这里无关,它可以通过线程或新进程来完成。
我真正需要的是:
有谁知道在 Java 中可以做到这一点的任何框架?
我一直在考虑这个问题已经有一段时间了,终于得到了一些你可能认为有用的东西。
我们的小“框架”的第一部分是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 = new WorkTask();
TaskRunner runner = new TaskRunner(new RetryingTaskWrapper(workTask, 5));
runner.start();
如果您只想运行WorkTask
一次而不重试,也可以:
WorkTask workTask = new WorkTask();
TaskRunner runner = new TaskRunner(workTask);
runner.start();
如果你愿意,你甚至可以WorkTask
在无限循环中运行你,而不必改变你WorkTask
自己。您只需要创建另一个 Wrapper
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();
如果任务中发生了令人讨厌的事情,产生它的父级将受到保护
所以我猜你有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 关于使用线程池的初步回答是正确的方法。