Как успешно получить доступ и зациклить ArrayList несколькими потоками? - PullRequest
2 голосов
/ 26 июля 2010

Мне нужна помощь в ArrayList. У меня есть массив строк. Я перебираю этот список и отправляю их в выходной поток один за другим. Пока я перебираю список и отправляю его, возможно, что другой поток добавит в него некоторые элементы. После отправки элемента его также необходимо удалить из списка.

Как мне этого добиться?

Ответы [ 4 ]

9 голосов
/ 26 июля 2010

Если элементы добавляются в конец списка, лучше использовать вместо них Очередь .Существуют различные поточно-ориентированные реализации, доступные в Java5 и более поздних версиях, включая ConcurrentLinkedQueue и LinkedBlockingQueue .

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

6 голосов
/ 26 июля 2010

Используйте правильную структуру данных для работы. Используйте ConcurrentLinkedQueue. Вот как он описывает себя в своем javadoc:

Неограниченная потокобезопасная очередь на основе связанных узлов. Эта очередь упорядочивает элементы FIFO (первым пришел-первым вышел). head очереди - это тот элемент, который находился в очереди самый длинный раз. Хвост очереди - это тот элемент, который находился в очереди кратчайшее время. Новые элементы вставляются в конец очереди, а операции поиска очереди получают элементы в начале очереди. A ConcurrentLinkedQueue является подходящим выбором, когда многие потоки будут совместно использовать доступ к общей коллекции.

2 голосов
/ 26 июля 2010

Я советую использовать некоторую реализацию BlockingQueue, так как ArrayList не предназначен для одновременных изменений:

class Producer implements Runnable {

  private BlockingQueue<String> queue;

  public Producer(BlockingQueue<String> queue) {
    this.queue = queue;
  }

  public void run() {
    try {
      queue.put("foo");
      queue.put("done");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

class Consumer implements Runnable {

  private final BlockingQueue<String> queue;

  public Consumer (BlockingQueue<String> queue) {
    this.queue = queue;
  }

  public void run() {
    try {
      String value = queue.take();
      while (!value.equals("done")) {
        value = queue.take();
        System.out.println(value);
      }
    } catch (InterruptedException e) {
       e.printStackTrace();
    }
  }
}

public class Main {
  public static void main(String[] args) throws Exception {
    BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
    Thread producer = new Thread(new Producer(queue));
    Thread consumer = new Thread(new Consumer(queue));
    producer.start();
    consumer.start();
    producer.join();
    consumer.join();
  }
}
0 голосов
/ 26 июля 2010

Предполагая, что это домашняя работа, я просто дам несколько советов.

  • оба потока могут synchronize в списке зарезервировать исключительный доступ
  • возвращает метод remove()объект удален
  • , который вы можете удалить из начала списка при добавлении в конец

Это должно помочь вам на вашем пути, это всегда помогает, если вы публикуете то, что у вас естьпока что мы можем основать совет на вашем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...