Как снизить нагрузку на ЦП при использовании ConcurrentLinkedQueue

234
23 мая 2017, 01:14

В общем: есть websocket сервер, в него приходят запросы, которые я обрабатываю и складываю ответы в очередь (LinkedBlockingQueue).

Обработкой ответов занимается класс ResponseExecutor. Так как он работает с блокирующей очердью, данным способом получается снизить нагрузку на ЦП в моменты когда очередь пуста, т.к. метод .take() блокирует поток, но когда в очереди накапливается много ответов - то их обработка может длится долгое время, потому что не все потоки задействованы. Вот код класса ResponseExecutor:

public class ResponseExecutor {
    private static final String TAG = ResponseExecutor.class.getSimpleName();
    private Log log = new Log(TAG, false);
    private final static int THREAD_POOL_SIZE = 16;
    private ExecutorService executorService;
    private LinkedBlockingQueue<ResponseValue> queue;
    private ConcurrentHashMap<ServiceUser, CopyOnWriteArrayList<WSDeviceSessionWrapper>> users;
    public ResponseExecutor(ConcurrentHashMap<ServiceUser, CopyOnWriteArrayList<WSDeviceSessionWrapper>> users, LinkedBlockingQueue<ResponseValue> queue) {
        this.executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE, new ExecutorThreadFactory());
        this.users = users;
        this.queue = queue;
    }
    public void processResponse(ResponseValue response) {
        this.queue.add(response);
        this.executorService.execute(new Consumer(this.users, this.queue));
    }
    private class Consumer implements Runnable {
        private ConcurrentHashMap<ServiceUser, CopyOnWriteArrayList<WSDeviceSessionWrapper>> users;
        private LinkedBlockingQueue<ResponseValue> queue;
        public Consumer(ConcurrentHashMap<ServiceUser, CopyOnWriteArrayList<WSDeviceSessionWrapper>> users, LinkedBlockingQueue<ResponseValue> queue) {
            this.users = users;
            this.queue = queue;
        }
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    ResponseValue value = queue.take();
                    process(value);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
    }
}

Я хочу вместо LinkedBlockingQueue использовать ConcurrentLinkedQueue но она съедает ЦП в моменты когда очередь пуста.

Вопрос: можно ли каким то образом использовать ConcurrentLinkedQueue и сделать так, что бы цикл while работал только когда в очереди есть данные?

P.S. была мысль прерывать все потоки после того как очередь стала пустой, но пока не до конца понял как это реализовать.

READ ALSO
текст караоке как отобразить?

текст караоке как отобразить?

Доброго времени суток! Подскажите, пожалуйста, может есть какие библиотеки или реализация отображения синхронизированного текста песниПодобное...

361
Как добавить к переменой число?

Как добавить к переменой число?

Есть переменная totalК ней необходимо добавить число, вводимое пользователем

237
Обновление записи в таблицe sqlite в java

Обновление записи в таблицe sqlite в java

Операция выполняется без ошибок, но обновление не происходит

213
Покупки внутри приложения

Покупки внутри приложения

ЗдравствуйтеВнедрим в приложение платежи с помощью стандартного гугловского примера TrivialDrive , все работает но почему то валюта всегда в рублях,...

187