Лучший способ адаптировать AbstractExecutorService Guava для распространения контекста (gRPC)? ⇐ JAVA
Лучший способ адаптировать AbstractExecutorService Guava для распространения контекста (gRPC)?
Я надеялся найти простой класс, который просто делает это в библиотеке контекста gRPC, но, к сожалению, безуспешно. Я хочу обернуть произвольный ExecutorService, чтобы он обернул свои задачи и распространил текущий контекст потока, который их отправил.
На данный момент у меня есть:
import io.grpc.Context; публичный финальный класс GrpcPropagatingExecutorService расширяет AbstractExecutorService { частный финальный делегат ExecutorService; public GrpcPropagatingExecutorService (делегат ExecutorService) { this.delegate = checkNotNull(делегат); } @Override protected RunnableFuture newTaskFor (Runnable runnable, значение T) { // Вариант 1: я мог бы разместить здесь код... super.newTaskFor(Context.current().wrap(runnable), value); } @Override protected RunnableFuture newTaskFor(Callable callable) { // ... и здесь. super.newTaskFor(Context.current().wrap(callable)); } @Override public void Execute (Выполняемая команда) { // Вариант 2: Или я мог бы разместить здесь код. super.execute(Context.current().wrap(команда)); } // Остальные методы тривиальны... } Мой вопрос: Какой подход является лучшим или они эквивалентны?
Размещение кода-обертки в newTaskFor() мне кажется удобнее, но оставляет проблему (т. е. что, если кто-то использует службу как простой Executor и напрямую вызывает < code>execute(), который не оборачивает данный Runnable?)
Разместить код оболочки только в execute() может быть и нормально, но только если он всегда вызывается в потоке, планирующем задачу, а не в каком-то рабочем потоке (это совсем не ясно). из документации, и теоретически я думаю, что это может быть нарушено службой, которая оборачивает это).
Размещение кода упаковки в обоих (ремень и подтяжки) возможно, но мне нужен новый тип, чтобы я мог обнаружить Runnables, которые уже упакованы (и я не думаю, что даже это особенно надежно, если честно).
Так мне придется просто переносить вещи в обоих местах и мучиться с переносом почти всех задач дважды, или я что-то упускаю?
РЕДАКТИРОВАТЬ. Альтернативная идея, о которой я только что подумал:
частный статический конечный класс GrpcPropagatingTask расширяет FutureTask { public GrpcPropagatingTask (Callable callable) { супер(Context.current().wrap(вызываемый)); } public GrpcPropagatingTask (Runnable runnable, результат V) { супер(Context.current().wrap(runnable), результат); } } И возвращаем это из методов newTaskFor(). Тогда в execute() я могу сделать:
@Override public void Execute (Выполняемая команда) { if (!(команда экземпляра GrpcPropagatingTask)) { команда = Context.current().wrap(команда); } делегат.execute (команда); } что, я думаю, развеет мои опасения по поводу прямого вызова execute().
Я надеялся найти простой класс, который просто делает это в библиотеке контекста gRPC, но, к сожалению, безуспешно. Я хочу обернуть произвольный ExecutorService, чтобы он обернул свои задачи и распространил текущий контекст потока, который их отправил.
На данный момент у меня есть:
import io.grpc.Context; публичный финальный класс GrpcPropagatingExecutorService расширяет AbstractExecutorService { частный финальный делегат ExecutorService; public GrpcPropagatingExecutorService (делегат ExecutorService) { this.delegate = checkNotNull(делегат); } @Override protected RunnableFuture newTaskFor (Runnable runnable, значение T) { // Вариант 1: я мог бы разместить здесь код... super.newTaskFor(Context.current().wrap(runnable), value); } @Override protected RunnableFuture newTaskFor(Callable callable) { // ... и здесь. super.newTaskFor(Context.current().wrap(callable)); } @Override public void Execute (Выполняемая команда) { // Вариант 2: Или я мог бы разместить здесь код. super.execute(Context.current().wrap(команда)); } // Остальные методы тривиальны... } Мой вопрос: Какой подход является лучшим или они эквивалентны?
Размещение кода-обертки в newTaskFor() мне кажется удобнее, но оставляет проблему (т. е. что, если кто-то использует службу как простой Executor и напрямую вызывает < code>execute(), который не оборачивает данный Runnable?)
Разместить код оболочки только в execute() может быть и нормально, но только если он всегда вызывается в потоке, планирующем задачу, а не в каком-то рабочем потоке (это совсем не ясно). из документации, и теоретически я думаю, что это может быть нарушено службой, которая оборачивает это).
Размещение кода упаковки в обоих (ремень и подтяжки) возможно, но мне нужен новый тип, чтобы я мог обнаружить Runnables, которые уже упакованы (и я не думаю, что даже это особенно надежно, если честно).
Так мне придется просто переносить вещи в обоих местах и мучиться с переносом почти всех задач дважды, или я что-то упускаю?
РЕДАКТИРОВАТЬ. Альтернативная идея, о которой я только что подумал:
частный статический конечный класс GrpcPropagatingTask расширяет FutureTask { public GrpcPropagatingTask (Callable callable) { супер(Context.current().wrap(вызываемый)); } public GrpcPropagatingTask (Runnable runnable, результат V) { супер(Context.current().wrap(runnable), результат); } } И возвращаем это из методов newTaskFor(). Тогда в execute() я могу сделать:
@Override public void Execute (Выполняемая команда) { if (!(команда экземпляра GrpcPropagatingTask)) { команда = Context.current().wrap(команда); } делегат.execute (команда); } что, я думаю, развеет мои опасения по поводу прямого вызова execute().
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Дублирующийся класс найден в модулях guava-26.0-android.jar и guava-jdk5-17.0.jar.
Anonymous » » в форуме Android - 0 Ответы
- 138 Просмотры
-
Последнее сообщение Anonymous
-