Билдирүүнүн автору Краковдон (Польша) программалык камсыздоону иштеп чыгуучу Гжегож Мирек. Ал Явада 6 жылдай мурун, университетте окуп жүргөндө эле өнүгүп баштаган жана ошондон бери ал бул жааттагы чеберчorгин талыкпастан жылмалоодо. Ал өзгөчө JVM иштешине жана оптималдаштырууга кызыкдар, бул тууралуу ал негизинен өзүнүн блогунда жазат .
Эң популярдуу Java интервью суроолорунун айрымдары төмөнкүлөрдү камтыйт: Иштебей турган тез жана коопсуз итераторлордун ортосунда кандай айырма бар? Буга эң жөнөкөйлөштүрүлгөн жооп: Итерация учурунда коллекция өзгөрбөсө, катасыз тез итератор ConcurrentModificationException ыргытат, бирок катасыз итератор андай эмес. Бул абдан маңыздуу угулат, бирок, интервьюер ийгorксиз деп эмнени айткысы түшүнүксүз бойдон калууда? Java тorнин спецификациялары бул терминди итераторлорго карата аныктаbyte. Бирок, төрт атаандаштык өзгөртүү стратегиясы бар.
Конкурстук өзгөртүү
Биринчиден, атаандаштык (же параллелдүү) модификация деген эмне экенин аныктап көрөлү. Айталы, бизде коллекция бар жана итератор активдүү болгондо, бул итератордон келбеген кээ бир өзгөрүүлөр болот. Бул учурда, биз атаандаштык модификациясын алабыз. Мен сизге жөнөкөй мисал келтирейин: бизде бир нече жип бар дейли. Биринчи жип итерацияланат, ал эми экинчи жип бир эле коллекциянын элементтерин киргизет же алып салат. Бирок, биз бир жиптүү чөйрөдө иштеп жатканда ConcurrentModificationException ала алабыз :List<String> cities = new ArrayList<>();
cities.add(“Warsaw”);
cities.add(“Prague”);
cities.add(“Budapest”);
Iterator<String> cityIterator = cities.iterator();
cityIterator.next();
cities.remove(1);
cityIterator.next(); // генерирует ConcurrentModificationException
Ийгorксиз
Жогорудагы code фрагменти катасыз тез итератордун мисалы болуп саналат . Көрүнүп тургандай, итератордон экинчи элементти алууга аракет кылып жатканда ConcurrentModificationException ыргытылган . Итератор коллекция түзүлгөндөн бери өзгөртүлгөнүн кайдан билет? Мисалы, коллекцияда дата/убакыт белгиси болушу мүмкүн, айталы, lastModified . Итератор түзүүдө бул талааны көчүрүп, аны итератор an objectинде сактоо керек. Андан кийин, кийинки() методу чакырылган сайын , сиз коллекциядагы lastModified маанисин итератордун көчүрмөсү менен салыштырып турасыз . Абдан окшош ыкма, мисалы, ArrayList классын ишке ашырууда колдонулат . Анда тизме канча жолу өзгөртүлгөнүн сактаган modCount инстанция өзгөрмөсү бар :final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
Белгилей кетчү нерсе, ийгorксиз итераторлор эң мыкты породада иштешет, башкача айтканда, ConcurrentModificationException бир эле учурда модификацияланган учурда ыргытылат деген кепилдик жок. Андыктан аларга ишенбешиңиз керек, тескерисинче, алар каталарды аныктоо үчүн колдонулушу керек. Кошумча эмес коллекциялар катасыз тез итераторлорду камсыз кылат.
Алсыз ырааттуулук
Java.util.concurrent топтомундагы көпчүлүк параллелдүү коллекциялар (мисалы, ConcurrentHashMap жана көпчүлүк кезекте ) начар ырааттуу итераторлорду камсыз кылат. Бул терминдин мааниси documentтерде абдан жакшы түшүндүрүлгөн :- Алар башка операциялар менен бир убакта иштетorши мүмкүн
- Алар эч качан ConcurrentModificationException ыргытышпайт
- Алар итератор так бир жолу түзүлгөн учурда болгон элементтерди басып өтүүгө кепилдик берилет жана кийинки өзгөртүүлөрдү чагылдыра алат (бирок талап кылынbyte).
GO TO FULL VERSION