Можно ли проверить время, затрачиваемое на вызов метода параллельно? - PullRequest
3 голосов
/ 10 января 2020

В классе обслуживания Spring Boot, допустим, я выполняю вызов метода processEvent().
Метод processEvent() может выполнять N различных функций, включая вызовы REST для других служб.

Как проверить время, затрачиваемое методом параллельно, и если оно пересекает порог, сделать что-то еще, например, выбросить исключение?

class EventService {  

    public void processEvent(ServiceContext context, Event event) {     

      // Field a time checker here for the below method.  
      processEvent(event);  
    }  
    public void processEvent(Event event) {  
      // this method does many things.  
    }  
}

Может ли это быть достигнуто с помощью CompletionService ? Если да, приведите пример!

РЕДАКТИРОВАТЬ:
Следующий код работает, но у меня есть один запрос:

public void processEvent(ServiceContext context, Event event) {  

LOGGER.debug("Timestamp before submitting task = {}", System.currentTimeMillis());  

  Future<EventResponse> future = executor.submit(() -> {  
    LOGGER.debug("Timestamp before invoking = {}", System.currentTimeMillis());
    EventResponse eventResponse = processEvent(event);  
    LOGGER.debug("Timestamp after invoking = {}", System.currentTimeMillis());  
    return eventResponse;  
  });  

  try {
    LOGGER.debug("Thread sleep starts at = {}", System.currentTimeMillis());
    Thread.sleep(5000);
    LOGGER.debug("Thread sleep ended at = {}", System.currentTimeMillis());
  } catch (InterruptedException e) {
    LOGGER.debug("Going to print stack trace....");
    e.printStackTrace();
  }  

  if (!future.isDone()) {
    future.cancel(true);
    LOGGER.debug("task executor cancelled at = {}", System.currentTimeMillis());
  } else {
    EventResponse response = future.get();
    LOGGER.debug("Received Event ID = {}", response.getEventDetailsList().get(0).getEventID());
    return response;
  }  

  LOGGER.debug("Going to return error response at = {}", System.currentTimeMillis());  
  throw new Exception("Message");  
}

Я получаю следующие журналы:

метка времени перед отправкой задачи = 1579005638324
спящий поток начинается с = 1579005638326
метка времени перед вызовом = 1579005638326
спящий поток заканчивается на = 1579005638526
Исполнитель задачи отменен при = 1579005638527
Возвращается ответ об ошибке при = 1579005638527
Метка времени после вызова = 1579005645228

Как "Метка времени после вызова" регистрируется после "Исполнителя задачи" отменено в "?

Ответы [ 2 ]

1 голос
/ 10 января 2020

Вы можете использовать сочетание стандартного ThreadPoolExecutor с ScheduledThreadPoolExecutor . Последний отменит отправку первого, если он все еще работает.

ThreadPoolExecutor executor = ...;

ScheduledThreadPoolExecutor watcher = ...;

Future<?> future = executor.submit(() -> { ...  })

watcher.schedule(() -> future.cancel(true), THRESHOLD_SECONDS, TimeUnit.SECONDS);

future.cancel(true) будет неактивным, если он завершится. Для этого, однако, вы должны знать, как обрабатывать межпотоковые коммуникации и отмены. cancel(true) говорит "Либо не позволяйте этому запускаться полностью, либо, если он выполняется, прерывайте поток, указывая, что нам нужно полностью и немедленно прекратить выполнение"

Оттуда ваш Runnable должен обрабатывать прерывание как условие остановки:

executor.submit(()-> {
   // do something
   if(Thread.currentThread().isInterrupted()) {
     // clean up and exit early
   }
   // continue doing something
});
1 голос
/ 10 января 2020

Вы можете использовать ThreadPoolTaskExecutor для отправки задания, затем поспать некоторое время, затем проверить, завершено ли задание, и прервать его, если оно все еще работает. Однако вы не можете просто убить задачу, вам придется периодически проверять наличие флага прерывания внутри самой задачи. Код будет что-то вроде:

@Autowired
private ThreadPoolTaskExecutor executor;

// ...

Future<?> future = executor.submit(() -> {

  doOneThing();

  if(Thread.interrupted()) {
    return;
  }

  doAnotherThing();

  if(Thread.interrupted()) {
    return;
  }

  // etc.
});

Thread.sleep(10000);

if (!future.isDone()) {
  future.cancel(true);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...