В ожидании обновления - PullRequest
       21

В ожидании обновления

0 голосов
/ 03 октября 2011

Как лучше всего ждать события / обновления. Например, я жду обновления этой структуры данных, прежде чем что-то делать. Реализация его внутри цикла - не лучший способ, так как он потребляет много процессорного времени, например:

while (true) {
   // keep checking the data structure
   // if data structure is updated
   //    break;
}
// do something here

Какой простой, но эффективный способ реализовать что-то подобное в Java?

Ответы [ 4 ]

1 голос
/ 03 октября 2011

wait-notifyAll является более эффективным способом, чем цикл.

Стандартная идиома для wait ():

synchronized (obj) {
    while(condition not hold) 
        obj.wait();
}

Но это примитивный способ управления потоками, лучше использовать классыjava.util.concurrent пакет.Более того, я выберу ответ Криса Дэйла, если столкнусь с такой проблемой.

1 голос
/ 03 октября 2011

Это действительно зависит от структуры остальной части вашей программы. Я бы, вероятно, начал с просмотра java.util.concurrent , чтобы узнать, подходит ли вам что-то там.

Примеры способов сделать это:

  • Фьючерсы - если вам нужно выполнить «работу», вы можете воспользоваться службой исполнения пула потоков, которая будет выполнять эту работу. Когда вы звоните submit () , чтобы выполнить вашу работу, вы получаете будущее, которое вы можете проверить или заблокировать, пока работа не будет завершена.

  • Очереди - Если у вас есть один компонент, выполняющий работу, и один компонент, выполняющий ожидание, вы можете сделать так, чтобы их связь выполнялась с очередями. Каждый раз, когда вы работаете с данными, их можно добавить в очередь. Вы можете использовать LinkedBlockingQueue и poll () для выполнения работы.

  • Слушатели - без одновременного использования, вы можете использовать шаблон Слушатель / Наблюдатель.

В зависимости от структуры вашего приложения существует множество различных опций.

0 голосов
/ 03 октября 2011

Предполагая, что вы используете многопоточность в приложении. Чтобы использовать один объект с несколькими потоками, вы должны использовать синхронизацию. Пока один поток инициализирует структуру данных, другой ожидает завершения инициализации. Эта логика обычно реализуется с использованием методов ожидания / уведомления, которые можно вызывать для любого объекта.

Рабочая резьба (и):

while (initialized) {
  synchronized (object) {
    object.wait();
  }
}

Поток инициализации:

synchronized (object) {
  // initialization
  initialized = true;
  object.notifyAll();
}

object - это структура данных, которая должна быть инициализирована. Флаг initialized, используемый для указания того, что инициализация завершена. Этот флаг лучше использовать, потому что иногда wait может быть завершен без соответствующего notify.

0 голосов
/ 03 октября 2011

Это пример кода, который я хотел бы сделать.

В этой логике я использую join метод в потоках.Это гарантирует, что все потоки объединяются, прежде чем выполнение основного потока продолжается.Я поставил TODO для мест, где вам нужно добавить свой код

import java.util.ArrayList;
import java.util.List;

public class MultiThread extends Thread{

    public void run() {
        System.out.println("Starting Thread - " + this.getName()+this.getThreadGroup());
        //TODO data structure is updated here
    }

    public static void main(String[] args) {
        List dataStructureList = new ArrayList() ;//TODO need to replace with list of data structure
        //TODO dataStructureList contain list of items
        Thread[] threadArr = new Thread[dataStructureList.size()];
        for (int j = 0; j < threadArr.length; j++) {
            threadArr[j] = new MultiThread();
            threadArr[j].setName("Thread " + j);
            threadArr[j].start();
        }
        try {
            for (int j = 0; j < threadArr.length; j++) {
                threadArr[j].join();
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("All thread finished");
        //TODO do something here

    }
}
...