[์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”] Item21 ์™„๋ฒฝ๊ณต๋žต. ConcurrentModificationException

2023. 3. 7. 11:40ใ†JAVA/Effective JAVA

728x90

 

item21. ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌํ˜„ํ•˜๋Š” ์ชฝ์„ ์ƒ๊ฐํ•ด ์„ค๊ณ„ํ•˜๋ผ. 

" p.137. ConcurrentModificationException"

 

 

ConcurrentModificationException

: This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

ํ˜„์žฌ ๋ฐ”๋€Œ๋ฉด ์•ˆ๋˜๋Š” ๊ฒƒ์„ ์ˆ˜์ •ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ 

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ConcurrentModificationException.html

 

ConcurrentModificationException (Java SE 11 & JDK 11 )

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible. For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating

docs.oracle.com

 

 

Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.

-> ๊ทผ๋ฐ ConcurrentModificationException์€ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์•„๋‹Œ ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ์—์„œ๋„ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

       List<Integer> numbers = List.of(1, 2, 3, 4, 5);
    
      
      List<Integer> numbers2 = new ArrayList<>(); // ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
      numbers2.add(1);
      numbers2.add(2);
      numbers2.add(3);
      numbers2.add(4);
      numbers2.add(5);

์šฐ์„  List.of ๋กœ ๋งŒ๋“  numbers์™€ ๊ทธ๋ƒฅ new Arraylist()ํ•ด์„œ ๋งŒ๋“  numbers2๋Š” ๊ฐ™์„๊นŒ? 

 

-> ๋‹ต์€ ์•„๋‹ˆ๋‹ค.

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) {
    return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5);
}

 ์™œ๋ƒํ•˜๋ฉด List.of ๋กœ ๋งŒ๋“  ์ปฌ๋ ‰์…˜์€ ImmutableCollection์œผ๋กœ ์ด๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค. 

for (Integer number : numbers)
{
   if (number == 3) {
      numbers.remove(number);
   }
}

๋”ฐ๋ผ์„œ ์ด๋ ‡๊ฒŒ remove๋ฅผ ํ•˜๋ ค๊ณ  ํ•˜๋ฉด UnsupportedOperation ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. 

for (Integer integer : numbers2)
{
   if (integer == 3) {
      numbers2.remove(integer);
   }
}

๊ทผ๋ฐ ์ด์ œ ์—ฌ๊ธฐ์„œ numbers2์˜ ๊ฐ’์„ ์ˆœํšŒํ•˜๋ฉด์„œ ๊ทธ ์ค‘ 3์„ removeํ•œ๋‹ค๊ณ  ํ•  ๋•Œ ConcurrentModificationException ์ด ๋ฐœ์ƒํ•œ๋‹ค. 

fail-fast iterator๋ฅผ ์‚ฌ์šฉํ•ด ์ปฌ๋ ‰์…˜์„ ์ˆœํšŒํ•˜๋Š” ์ค‘์— ์ปฌ๋ ‰์…˜์—์„œ remove ํ•˜๋ฉด ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ์ƒํ™ฉ์—์„œ๋„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. 

 

 

์ด ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ์ปฌ๋ ‰์…˜์˜ ํŠน์ • ๊ฐ’์„ ์ œ๊ฑฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด 

๋ฐฉ๋ฒ•1) iterator remove ์‚ฌ์šฉ 

for (Iterator<Integer> iterator = numbers2.iterator(); iterator.hasNext();)
{
   Integer integer = iterator.next();
   if (integer == 3) {
      iterator.remove(); 
   }
}

์œ„์—์„œ๋Š” iterator๊ฐ€ Collection์— ๊ฐ’์ด ์ œ๊ฑฐ๋œ์ง€ ๋ชฐ๋ž์ง€๋งŒ iterator removeํ•˜๋ฉด iterator๊ฐ€ ์ง์ ‘ ์ œ๊ฑฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. 

 

๋ฐฉ๋ฒ•2) index ์‚ฌ์šฉํ•˜๊ธฐ 

for (int i = 0; i< numbers2.size(); i++)
{
   if (numbers2.get(i) == 3) {
      numbers2.remove(numbers2.get(i));
   }
}

์ด ๋ฐฉ๋ฒ•์€ ๊ทธ๋ƒฅ index ๊ฐ’์„ ์‚ฌ์šฉํ•ด์„œ ์ œ๊ฑฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. 

 

 

๋ฐฉ๋ฒ•3) removeIf ์‚ฌ์šฉํ•˜๊ธฐ 

numbers2.removeIf(number -> number == 3);
numbers2.forEach(System.out::println);

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. removeIf ์•ˆ์— filter๋กœ ์กฐ๊ฑด์ด true์ด๋ฉด ์ด์ œ ๊ทธ ๊ฐ’์„ ์ œ๊ฑฐํ•ด์ค€๋‹ค. 

 

 

 

 

 

 

 

 

 

 

728x90