Повторное выполнение Runnable в потоке

231
06 марта 2017, 10:34

Есть класс Worker который содержит в себе очередь и при добавлении в очередь новой строки должен выполнить некую работу.

При создания потока в него передаеться Runnable который будет запущен после вызова метода Thread.start(). После этого в Worker будут добавляться в очередь новые задачи через мтеод .add() и вот тут уже метод Runnable.run() будет вызван снова но уже в ручную. Вопрос: меня интересует можно ли так делать, в смысле вызывать метод .run() вручную. P.S. в конструкторе потока я устанавливаю ему имя Worker но потом потом когда проверяю имя потока в Runnable то имя у него 'main', почему так происходит?

public class Worker {
    private static final String TAG = Worker.class.getSimpleName();
    private static final Log log = new Log(TAG);
    private static Worker instance;
    private ConcurrentLinkedQueue<String> queryQueue;
    private WorkerThread workerThread;
    public static Worker getInstance() {
        if (instance == null) {
            instance = new Worker();
        }
        return instance;
    }
    private Worker() {
        source = DBConnectionPool.getInstance().getSource();
        queryQueue = new ConcurrentLinkedQueue<>();
        workerThread = new WorkerThread(new Consumer(this.queryQueue));
        workerThread.start();
    }
    public void add(String s) {
        this.queryQueue.add(s);
        workerThread.execute();
    }
    class WorkerThread extends Thread {
        protected Consumer consumer;
        public WorkerThread(Consumer target) {
            this.consumer = target;
            //set thread name
            this.setName(this.getClass().getSimpleName()); //name is Worker
        }
        public void execute() {
            this.consumer.run();
        }
    }
    class Consumer implements Runnable {
        private ConcurrentLinkedQueue<String> queue;
        public Consumer(ConcurrentLinkedQueue<String> queue) {
            this.queue = queue;
        }
        @Override
        public void run() {
            Thread.currentThread().getName(); // name is: 'main'
            //do simething
        }
    }
}

Добавляю элементы в очередь так:

Worker.getInstance().add("exampleString");
Answer 1

Вызывать метод run вручную не очень хорошо. Лучше сделать так чтобы Consumer сам отвечал за обработку поступающих строк.

ConcurrentLinkedQueue использует wait-free алгоритм и не блокирует поток, который достает элемент, если очередь пуста.

This implementation employs an efficient "wait-free" algorithm based on one described in Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms by Maged M. Michael and Michael L. Scott.

Данная имплементация очереди обычно рассчитана на интенсивный обмен между производителем и потребителем данных. Также когда кол-во конкурирующих потоков велико.

Так как у вас только один worker вам будет лучше заменить ConcurrentLinkedQueue на LinkedBlockingQueue и использовать метод take. Этот метод будет блокировать worker-поток пока в очереди не появятся данные.

READ ALSO
Тратятся ли ресурсы на элементы layout, которые не видны (не влезают) на экран?

Тратятся ли ресурсы на элементы layout, которые не видны (не влезают) на экран?

Я так думаю, что тратятся: и кнопки создаются, неважно gone они или visible, или вообще находятся вне области экрана, и картинки загружаются? Правильно...

233
Алгоритм слияния элементов коллекций

Алгоритм слияния элементов коллекций

Здравствуйте, вот суть моей проблемы, есть несколько коллекций:

273
Как исправить &ldquo;Task &#39;Som&#39; not found in root project &#39;SomaAndroid&#39; &rdquo;?

Как исправить “Task 'Som' not found in root project 'SomaAndroid' ”?

Как исправить Task 'Som' not found in root project 'SomaAndroid'? Где искать и с чем она связана? Возникла после обновления Android Studio

305