Как можно сделать так, чтобы этот код вызова веб-службы с задержкой Java использовал меньше процессоров? - PullRequest
0 голосов
/ 04 марта 2019

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

При использовании YourKit Profiler вызов, использующий значительное количество процессоров, составляет

 java.util.concurrent.locks.AbstractQueuedSynchronizer.aquireQueued()

Мой метод задержки ниже

    public class SearchServer
    {

        private static java.util.concurrent.locks.Lock delayLock = new ReentrantLock();
        private static AtomicInteger queryQueue = new AtomicInteger();
        private static AtomicLong queryDelay = new AtomicLong();

        static void doDelayQuery()
        {
            delayLock.lock();
            try
            {
                if(isUserCancelled())
                {
                    return;
                }
                //Ensure only send one query a second
                Date currentDate = new Date();
                long delay = currentDate.getTime() - querySentDate.getTime();
                if (delay < delayInMilliseconds)
                {
                    try
                    {
                        long delayBy = delayInMilliseconds - delay;
                        queryDelay.addAndGet(delayBy);
                        Thread.sleep(delayBy);
                        logger.info(Thread.currentThread().getName() + ":Delaying for " + delayBy + " ms");
                    }
                    catch (InterruptedException ie)
                    {
                        Thread.currentThread().interrupt();
                        throw new UserCancelException("User Cancelled whilst thread was delay sleeping");
                    }
                }
            }
            finally
            {
                //We set before unlocking so that if another thread enters this method before we start query we ensure they
                //do not skip delay just because the query that this thread has delayed for has started
                querySentDate = new Date();
                delayLock.unlock();
            }

        }
    }

1 Ответ

0 голосов
/ 05 марта 2019

Хорошо, с помощью Google Guava Library это оказалось удивительно просто

import com.google.common.util.concurrent.RateLimiter;
public class SearchServer
{
     private static RateLimiter rateLimiter = RateLimiter.create(1.0d);

     static void doDelayQuery()
     {
        rateLimiter.acquire();
     }

     public doQuery()
     ..................
}

Несмотря на то, что ключевым отличием является то, что раньше я взял время предыдущего вызова, поэтому не ждал полной секунды между вызовами, так чтополучить аналогичную пропускную способность Я изменил RateLmiter для использования 2.0d

Профилирование больше не показывает попадание процессора в этой области.

...