1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/jd-platform-opensource-asyncTool

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
QuickStart.md 10 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 02.12.2024 07:51 d5cc747

Если вам нужен только этот фреймворк, можете сразу посмотреть ниже.

Если вы хотите глубже понять, как этот фреймворк реализуется шаг за шагом, от получения требований до каждого этапа размышлений, почему каждый класс спроектирован именно так, и почему существуют эти методы, то есть как разработать этот фреймворк с нуля, автор открыл специальный раздел на CSDN (https://blog.csdn.net/tianyaleixiaowu/category_9637010.html), где подробно рассказывается о разработке промежуточного программного обеспечения, включая, но не ограничиваясь этим небольшим фреймворком. Коллеги из JD могут также искать информацию об ERP на CF.

Коллеги из JD используют следующий maven для ссылки:

            <dependency>
                <groupId>com.jd.platform</groupId>
                <artifactId>asyncTool</artifactId>
                <version>1.4.2-SNAPSHOT</version>
            </dependency>

Для внешних пользователей рекомендуется использовать пакет, собранный на jitpack.io: Сначала добавьте узел repositories:

        <repositories>
        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>
    </repositories>

Затем добавьте следующую зависимость maven:

        <dependency>
        <groupId>com.gitee.jd-platform-opensource</groupId>
        <artifactId>asyncTool</artifactId>
        <version>V1.4-SNAPSHOT</version>
    </dependency>

Основные компоненты

worker: это наименьшая единица выполнения задачи. Обычно это сетевой вызов или длительная операция.

T и V — два универсальных типа, которые представляют тип входных и выходных данных соответственно. Например, если эта длительная операция имеет входные данные String и результат Integer после завершения, можно использовать универсальные типы для определения. Между различными workers нет связи, и они могут иметь разные типы входных и выходных данных.

/**
 * 每个 наименьший блок выполнения должен реализовывать этот интерфейс
 * @author wuweifeng написал 2019-11-19.
 */
public interface IWorker<T, V> {
    /**
     * Выполните длительную операцию здесь, например, rpc-запрос или IO
     *
     * @param object
     *         объект
     */
    V action(T object, Map<String, WorkerWrapper> allWrappers);

    /**
    * Возвращает значение по умолчанию при тайм-ауте или ошибке
    * @return значение по умолчанию
    */
    V defaultValue();
}

callBack: это обратный вызов для каждого worker. После завершения выполнения worker вызовет этот интерфейс с результатами успеха или неудачи, исходными входными данными и подробными результатами.

/**
* Каждый блок выполнения вызывает этот интерфейс после завершения
* Те, кто хочет отслеживать результаты выполнения, должны реализовать этот интерфейс
* @author wuweifeng написал 2019-11-19.
*/
public interface ICallback<T, V> {

void begin();

/**
* Операция с длительным временем выполнения завершена, и значение будет введено в значение
*
*/
void result(boolean success, T param, WorkResult<V> workResult);
}

wrapper: объединяет worker и callback, является наименьшей единицей планирования. Путем организации взаимосвязи между оболочками достигается цель упорядочивания различных рабочих блоков.

Универсальные типы оболочки такие же, как и у worker, что определяет типы ввода и вывода.

Например:

введите сюда описание изображения

0 выполняется одновременно с 1 и 2, а 1\2 завершаются одновременно, затем выполняется 3. 3 будет ждать завершения 2. В это время вы можете определить worker:

/**
* @author wuweifeng написал 2019-11-20.
*/
public class ParWorker1 implements IWorker<String, String>, ICallback<String, String> {

@Override
public String action(String object) {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "result = " + SystemClock.now() + "---param = " + object + " from 1";
}

@Override
public String defaultValue() {
    return "worker1--default";
}

@Override
public void begin() {
    //System.out.println(Thread.currentThread().getName() + "- start --" + System.currentTimeMillis());
}

@Override
public void result(boolean success, String param, WorkResult<String> workResult) {
    if (success) {
        System.out.println("callback worker1 success--" + SystemClock.now() + "----" + workResult.getResult()
                + "-threadName:" +Thread.currentThread().getName());
    } else {
        System.err.println("callback worker1 failure--" + SystemClock.now() + "----"  + workResult.getResult()
                + "-threadName:" +Thread.currentThread().getName());
    }}
}

Через этот класс вы можете видеть, что действие внутри представляет собой вашу длительную операцию, начало — это обратный вызов при запуске задачи, результат — это обратный вызов после завершения worker. Когда вы объединяете несколько блоков выполнения, каждый шаг находится под вашим контролем. Если произойдет сбой, будет предоставлено настраиваемое значение по умолчанию. Это невозможно сделать с помощью CompleteableFuture.

Установка учебника

Код небольшой, просто скопируйте пакет.

Использование инструкции

  1. 3 задачи выполняются параллельно
        ParWorker w = new ParWorker();
        ParWorker1 w1 = new ParWorker1();
        ParWorker2 w2 = new ParWorker2();

        WorkerWrapper<String, String> workerWrapper2 =  new WorkerWrapper.Builder<String, String>()
``` ```
.worker(w2)
    .callback(w2)
    .param("2")
    .build();

WorkerWrapper<String, String> workerWrapper1 =  new WorkerWrapper.Builder<String, String>()
    .worker(w1)
    .callback(w1)
    .param("1")
    .build();

WorkerWrapper<String, String> workerWrapper =  new WorkerWrapper.Builder<String, String>()
    .worker(w)
    .callback(w)
    .param("0")
    .build();

long now = SystemClock.now();
System.out.println("begin-" + now);

Async.beginWork(1500, workerWrapper, workerWrapper1, workerWrapper2);
// Async.beginWork(800, workerWrapper, workerWrapper1, workerWrapper2);
// Async.beginWork(1000, workerWrapper, workerWrapper1, workerWrapper2);

System.out.println("end-" + SystemClock.now());
System.err.println("cost-" + (SystemClock.now() - now));
System.out.println(Async.getThreadCount());

System.out.println(workerWrapper.getWorkResult());
Async.shutDown();
ParWorker w = new ParWorker();
ParWorker1 w1 = new ParWorker1();
ParWorker2 w2 = new ParWorker2();
ParWorker3 w3 = new ParWorker3();

WorkerWrapper<String, String> workerWrapper3 =  new WorkerWrapper.Builder<String, String>()
    .worker(w3)
    .callback(w3)
    .param("3")
    .build();

WorkerWrapper<String, String> workerWrapper2 =  new WorkerWrapper.Builder<String, String>()
    .worker(w2)
    .callback(w2)
    .param("2")
    .next(workerWrapper3)
    .build();

WorkerWrapper<String, String> workerWrapper1 =  new WorkerWrapper.Builder<String, String>()
    .worker(w1)
    .callback(w1)
    .param("1")
    .next(workerWrapper3)
    .build();

WorkerWrapper<String, String> workerWrapper =  new WorkerWrapper.Builder<String, String>()
    .worker(w)
    .callback(w)
    .param("0")
    .next(workerWrapper1, workerWrapper2)
    .build();


long now = SystemClock.now();
System.out.println("begin-" + now);

Async.beginWork(3100, workerWrapper);
// Async.beginWork(2100, workerWrapper);

System.out.println("end-" + SystemClock.now());
System.err.println("cost-" + (SystemClock.now() - now));

System.out.println(Async.getThreadCount());
Async.shutDown();
``` Зависимость от результатов выполнения других worker-ов в качестве входных параметров.

Можно получить результат выполнения любого блока по его идентификатору из параметров action, но необходимо учитывать порядок выполнения: если блок ещё не был выполнен, вызов WorkerResult.getResult() вернёт null!

Другие подробности см. в тестовых классах в пакете test. Поддерживаются различные комбинации и последовательности.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/jd-platform-opensource-asyncTool.git
git@api.gitlife.ru:oschina-mirror/jd-platform-opensource-asyncTool.git
oschina-mirror
jd-platform-opensource-asyncTool
jd-platform-opensource-asyncTool
master