Java 为批处理任务实现通用进度跟踪器
我目前正在从事一个项目,该项目有许多后台任务需要执行。创建每个任务,然后将其发送到一个并发服务,该服务管理所有任务的执行过程。每个任务在执行期间都存储在数据库表中 我的困境是,每个任务都执行非常特定的功能,一般来说,大多数任务都委托给系统另一部分的服务,工作的主要部分完成,然后任务返回 目前我已经实现了一个非常简单的系统来跟踪任务的进度,它工作得很好,但是执行的每个任务都需要添加大量额外的代码来适应它所委托的服务的功能 例如,我的任务有一个方法:Java 为批处理任务实现通用进度跟踪器,java,background-process,generic-programming,Java,Background Process,Generic Programming,我目前正在从事一个项目,该项目有许多后台任务需要执行。创建每个任务,然后将其发送到一个并发服务,该服务管理所有任务的执行过程。每个任务在执行期间都存储在数据库表中 我的困境是,每个任务都执行非常特定的功能,一般来说,大多数任务都委托给系统另一部分的服务,工作的主要部分完成,然后任务返回 目前我已经实现了一个非常简单的系统来跟踪任务的进度,它工作得很好,但是执行的每个任务都需要添加大量额外的代码来适应它所委托的服务的功能 例如,我的任务有一个方法: @Override public void ex
@Override
public void execute() {
service.calculateAverage();
}
然后在服务中相应地:
public float calculateAverage() {
float total = 0.0f;
for (i = 0; i < 20; i++) {
total += i;
}
return total / 20;
}
public float calculateAverage(){
总浮点数=0.0f;
对于(i=0;i<20;i++){
总数+=i;
}
返回总数/20;
}
跟踪这项工作的进度相当简单,我只是在数据库中的任务超过某个迭代阈值后更新它。然而,将其泛化是一项相当艰巨的任务,因为执行的每个任务都可能完全委托给不同的服务。这意味着在每个服务中,我需要添加特定于该服务实现的代码
我做了一些搜索,但似乎找不到任何好的模式来帮助创建一个通用系统来跟踪每个任务的进度。任何指针,甚至只是查找或阅读的地方都很好。如果您让您的服务使用自己的
迭代器,而不是让它创建循环
class SumService {
private float calculateSum(Iterable<Integer> i) {
float total = 0.0f;
for (Integer x : i) {
total += x;
}
return total;
}
}
这将管理职责的分离。对于服务来说,它只是一个Iterable
,而对于进度跟踪器来说,它将在需要时提供当前进度
我称之为模式,因为有一个对象正好做两件事。它允许您将两个进程绑定到一个对象中
我选择了最简单的进度指标——介于0
和1
之间的double
。我相信你可以做得更好。这确实帮了大忙,我目前正在将其付诸实施,而且似乎效果非常好。我从来没有想过要这样做。
/**
* State of progress - returns a double result between 0 and 1.
*
* Will be called repeatedly by the progress tracker.
*/
interface Progress {
public double getProgress();
}
/**
* The progress tracker.
*/
static class ProgressTracker {
// All processes are registered.
static void registerProgressor(Progress p) {
// Add it to mmy list of people to watch.
}
}
/**
* An Iterable that reports its progress.
*/
class ProgressingIterable<T> implements Iterable<T>, Progress {
// The iterable we are hosting.
final Iterable<T> it;
// How far we are to go.
final int steps;
// Where we're at now.
volatile int at = 0;
public ProgressingIterable(Iterable<T> it, int steps) {
this.it = it;
this.steps = steps;
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
// Grab an Iterator from the Iterable.
Iterator<T> i = it.iterator();
@Override
public boolean hasNext() {
// Delegate.
return i.hasNext();
}
@Override
public T next() {
// Keep track of the steps.
at++;
return i.next();
}
};
}
@Override
public double getProgress() {
// How are we doing?
return (double) at / (double) steps;
}
}
/**
* A range (from http://stackoverflow.com/a/6828887/823393).
*
* @param begin inclusive
* @param end exclusive
* @return list of integers from begin to end
*/
public static List<Integer> range(final int begin, final int end) {
return new AbstractList<Integer>() {
@Override
public Integer get(int index) {
return begin + index;
}
@Override
public int size() {
return end - begin;
}
};
}
/**
* A process.
*/
class Process {
ProgressingIterable<Integer> progress = new ProgressingIterable<>(range(0, 20), 20);
public void execute() {
// Register the Progress
ProgressTracker.registerProgressor(progress);
// Make the service use my progress object.
service.calculateSum(progress);
}
}
// The service it uses.
SumService service = new SumService();