2015-07-23 4 views
1

В настоящее время я работаю над проектом, который выполняет ряд фоновых задач, которые выполняются. Каждая задача создается, а затем отправляется на параллельную службу, которая управляет процессом выполнения всех задач. Каждая задача хранится в таблице базы данных в течение продолжительности ее выполнения.Реализация единого отслеживания прогресса для перетаскиваемых задач

Моя дилемма заключается в том, что каждая задача выполняет очень конкретные функции, и в большинстве случаев большинство делегатов на службу в другой части системы, основная работа выполняется, а затем возвращается задача.

В настоящее время у меня очень простая система, которая отслеживает ход выполнения задачи, она работает хорошо, однако каждая выполняемая задача требует добавления большого количества дополнительного кода для обеспечения функциональности предоставляемых им услуг.

Так как пример моя задача будет иметь метод:

@Override 
public void execute() { 
    service.calculateAverage(); 
} 

И затем, соответственно, на службе:

public float calculateAverage() { 
    float total = 0.0f; 
    for (i = 0; i < 20; i++) { 
     total += i; 
    } 
    return total/20; 
} 

Отслеживание прогресса это довольно просто, я просто обновить мой задачи в базе данных после того, как она прошла определенный порог итераций. Тем не менее, для его создания это довольно сложная задача, так как каждая выполняемая задача может делегировать другую службу полностью. Это означает, что в каждой службе мне нужно добавить код, специфичный для реализации для этой службы.

Я немного поработал, и я не могу найти никаких хороших шаблонов, которые могут помочь в создании общей системы для отслеживания прогресса каждой задачи. Любые указатели или даже просто места для просмотра или чтения были бы хорошими.

ответ

2

Если вы сделаете свой сервис, используйте свой собственный Iterator, а не создавайте цикл.

class SumService { 

    private float calculateSum(Iterable<Integer> i) { 
     float total = 0.0f; 
     for (Integer x : i) { 
      total += x; 
     } 
     return total; 
    } 

} 

Вы можете создать Iterable, что следить за прогрессом и докладов о прогрессе трекера.

/** 
* 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(); 

Это управляет разделением обязанностей. К сервису относится только Iterable, а к отслеживателю прогресса он будет доставлять текущий прогресс всякий раз, когда его спрашивают.

Я называю это шаблоном Janus, потому что у вас есть один объект, который выполняет ровно две вещи. Это позволяет вам связать два процесса вместе в одном объекте.

Я выбрал самый простой индикатор прогресса - a double между 0 и 1. Я уверен, что вы могли бы сделать гораздо лучшую работу.

+1

Это действительно помогло, я в настоящее время внедряю его в действие, и, похоже, он работает очень хорошо. Никогда бы не подумал сделать это таким образом. – Daniel

Смежные вопросы