我正在寻求在Java中实现一个我生成任务的机制。该任务的作用实际上与此无关,可以通过线程或新进程完成。
我真正需要的是:
有没有人知道在Java中可以做到的任何框架?
答案 0 :(得分:2)
我一直在思考这个问题已经有一段时间了,最后得到了你认为有用的东西。
我们的小“框架”的第一部分是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();
答案 1 :(得分:2)
答案 2 :(得分:1)
如果任务中发生了令人讨厌的事情,那么产生它的父母就会受到保护
所以我猜你有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关于使用线程池的初步答案是正确的方法。