2017-02-20 3 views
0

У меня есть списокБезопасно ли перебирать один и тот же список одновременно?

testList= new ArrayList<String>(); // gets initialized once at the very beginning init(). This list never changes. It's static and final. 

У меня есть статический метод, который проверяет, если входное значение в этом списке:

public static boolean isInList (String var1) 
      throws InterruptedException { 

     boolean in = false; 

     for (String s : testList) { 

      if (s.equals(var1)) 
      { 
       in = true; 
       break; 
      } 
     } 

     return in; 
    } 

У меня есть много потоков, которые используют этот метод одновременно и проверить, если в этом списке есть определенное значение. Кажется, он работает нормально. Однако я не уверен, что это безопасно. Правильно ли я делаю это? Это потокобезопасность?

+0

Да, если вы не добавление/удаление/обновление элементов на список. Кстати, используйте другую структуру данных для таких запросов. Например, hashmap – raven

+3

Почему вы не используете 'testList.contains (var1)'? – RealSkeptic

ответ

0

Пока вы можете гарантировать, что никто не пишет в списке, это безопасно.

Обратите внимание, что даже если список static и final, код самого не гарантирует, что этот список не изменял. Вместо этого я рекомендую использовать Collections.unmodifiableList(), потому что он гарантирует, что ни один элемент не будет добавлен или удален из списка.


Кстати, вы можете переписать код так:

public static boolean isInList(String var1) { 
    for (String s : testList) { 
     if (Objects.equals(s, var1)) { 
      return true; 
     } 
    } 
    return false; 
} 

или просто

testList.contains(var1); 
3

Это поточно-безопасный, если нить не изменяет список, пока другие нити его читают.

Если вы используете итераторы по списку, они будут «сбой» (как в броске ConcurrentModificationException), если список изменен под ними. Другие способы доступа (то есть get(n)) не будут вызывать исключение, но могут возвращать неожиданные результаты.

Все это подробно описано в Javadoc для List и ArrayList, которые вы должны тщательно изучить.

+0

И, как раз отметить, список должен быть безопасно опубликован для каждого из потоков в первую очередь. * Большинство * методов обработки ссылок на потоки будут в порядке; просто не сохраняйте его в нестабильном статическом поле и попробуйте прочитать потоки. Также следует отметить, что для списка, не связанного с потоками (например, ArrayList), вы не можете полагаться на неустойчивое поведение ConcurrentModificationException, поскольку те самые значения, которые он использует для проверки, подвержены условиям гонки. – yshavit

+0

Метод итератора списка (который вызывается в вашем цикле for) возвращает новый экземпляр итератора, каждый раз, когда он вызывается, поэтому вы можете циклически перебирать список много раз одновременно без проблем – Bruno

2

ArrayList не является потокобезопасным объектом. Он может работать для вас сейчас, но в целом при работе с потоками вы должны убедиться, что используете поточно-безопасные объекты, которые будут работать с вашими потоками, как вы ожидаете.

Вы можете использовать Collections.synchronizedList()

testList = Collections.synchronizedList(new ArrayList<String>());

Смежные вопросы