Java'da en iyi eşzamanlılık listesini seçme [kapalı]


101

İş parçacığı havuzumun sabit sayıda iş parçacığı var. Bu konuların sık sık paylaşılan bir listeden yazması ve okuması gerekir .

Öyleyse, java.util.concurrentpaketteki hangi veri yapısı (bir Liste olsa iyi olur, monitörsüz olmalıdır) bu durumda en iyisidir?


5
Bu koleksiyonla ne yapmak istediğinize bağlı. Blog yazıma bakın (.Net ile ilgili olmasına rağmen, kavramlar aynıdır). A ile doğru iş parçacığı güvenli kodu yazmanız pek olası değildir List.
SLaks

1
Şimdi, CopyOnWriteArrayList kullanıyorum , ancak ConcurrentModificationException istisnası hala ara sıra atılıyor.
象 嘉 道

2
İnsanların daha iyi yanıt verebilmesi için lütfen koleksiyonda ne yaptığınız hakkında daha fazla bilgi ekleyin, aksi takdirde bu sadece bir tahmindir.
mattsh

2
ConcurrentModificationExceptionBir senkronizasyon sorunu gelmeyebilir; aynı zamanda, örneğin koleksiyondan bir öğeyi çıkarmaya çalıştığınız bir koleksiyon üzerinden bir döngü içinde ortaya çıkar.
toto2

1
Paketin bir parçası olmadığını biliyorum ama birisi denedi Vectormi?
WesternGun

Yanıtlar:


100

olsa iyi olur List

Sadece List içinde uygulama java.util.concurrentolduğunu CopyOnWriteArrayList .O . Travis Webb'in bahsettiği gibi senkronize bir liste seçeneği de var.

Bununla birlikte, bir olması gerektiğine emin misin List? Eşzamanlı Queues ve Maps için çok daha fazla seçenek vardır (ve Sets'den Maps yapabilirsiniz) ve bu yapılar, paylaşılan bir veri yapısı ile yapmak istediğiniz birçok şey türü için en mantıklı olma eğilimindedir.

Kuyruklar için çok sayıda seçeneğiniz vardır ve hangisi en uygun olanı onu nasıl kullanmanız gerektiğine bağlıdır:


15
CopyOnWriteArrayListyazmada çok pahalı olma dezavantajına sahiptir (ancak okumalar için ucuzdur) Eğer çok fazla yazma yapıyorsanız, senkronize edilmiş bir Liste veya kuyrukla daha iyi durumda olursunuz.
Peter Lawrey

69

Herhangi bir Java koleksiyonu şu şekilde İş Parçacığı için güvenli hale getirilebilir:

List newList = Collections.synchronizedList(oldList);

Veya iş parçacığı açısından güvenli yepyeni bir liste oluşturmak için:

List newList = Collections.synchronizedList(new ArrayList());

http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List)


7
Bu nedenle, java.util.concurrent'da hiçbir liste uygulaması bulamazsınız - Uhm, ConcurrentHashMapbir Collections.synchronizedMapyöntem olsa bile bir var .
aioobe

7
Javadocs'u okuyun ConcurrentHashMap. Senkronizasyon uygulamasının ayrıntıları farklıdır. synchronizedYöntemleri kullanmak Collectionstemelde sınıfı bir Java monitörüne sarar. ConcurrentHashMapdaha akıllı eşzamanlılık özellikleri kullanır.
Travis Webb

1
Evet. Yine de, son cümlenizi bir nevi geçersiz kılıyor.
aioobe

1
Bir monitör kullanıyorsanız, programın performansı gerçekten kötü:
象 嘉 道

6
Eklemek gerekirse, newList üzerinden yineleme iş parçacığı açısından güvenli değildir. !!
bluelurker

9

Listenin boyutu sabitse, bir AtomicReferenceArray kullanabilirsiniz . Bu, bir yuvaya endekslenmiş güncellemeler gerçekleştirmenize izin verir. Gerekirse bir Liste görünümü yazabilirsiniz.


7

ConcurrentLinkedQueuekilitsiz bir kuyruk kullanır (daha yeni CAS talimatına göre ).


7
... bu Listarayüzü uygulamaz .
aioobe

1
eSniff, List.set(int index, Object element)ConcurrentLinkedQueue ile uygulamaya nasıl devam edersiniz ?
John Vint

4
Çoğu Liste özgü yöntemlerle ya bir kullanarak uygulanabilir olacak değildir Queue(örneğin, belirli bir endeksinde ekle / set) ya da olabilir çeşit uygulanacak ait ama (bir dizin aldığım) verimsiz olacaktır. Bu yüzden gerçekten bitirebileceğini sanmıyorum. Bununla birlikte Queue, OP neden a'ya ihtiyaç duyduklarını gerçekten açıklamadığı için a'nın önerisinin iyi olduğunu düşünüyorum List.
ColinD

1
@ColinD, aradığım cevap buydu. CLQ'nun bir Listeye sarılamaması için iyi sebepler var. Kabul etsem de, Kuyruk arayüzünü göz ardı edemem.
John Vint

1
❗️ Şunu belirtmek gerekir: "Çoğu koleksiyondan farklı olarak, boyut yönteminin sabit zamanlı bir işlem OLMADIĞINA dikkat edin. Bu kuyrukların eşzamansız doğası nedeniyle, öğelerin mevcut sayısını belirlemek öğelerin geçişini gerektirir."
βξhrαng

6

Doug Lea tarafından Paul Martin'in "A Practical Lock-Free Doubly-Linked List" e dayalı olarak yazdığı ConcurrentDoublyLinkedList'e bakmak isteyebilirsiniz . Java.util.List arayüzünü uygulamaz, ancak bir Listede kullanacağınız çoğu yöntemi sunar.

Javadoc'a göre:

Bir Deque (çift uçlu kuyruk) için eşzamanlı bağlantılı liste uygulaması. Eşzamanlı ekleme, kaldırma ve erişim işlemleri, birden çok iş parçacığı üzerinde güvenli bir şekilde yürütülür. Yineleyiciler, zayıf bir şekilde tutarlıdır , yineleyicinin yaratılmasının bir noktasında veya bu zamandan bu yana dekorun durumunu yansıtan öğeler döndürür. Onlar do değil ConcurrentModificationException atmak ve diğer operasyonlar ile eş zamanlı devam edebilirsiniz.


3

Ayar yeterliyse, ConcurrentSkipListSet kullanılabilir. (Uygulanması, bir atlama listesini uygulayan ConcurrentSkipListMap'e dayanmaktadır .)

Beklenen ortalama zaman maliyeti, içerme, ekleme ve kaldırma işlemleri için log (n) 'dir; boyut yöntemi sabit zamanlı bir işlem değildir.


Ama liste değil ayarlandı. aynı hashcod emultiple'ine sahip nesneleri ekleyemezsiniz.
Tuğrul Karakaya

Yazdığım nedeni budur: "seti yeterli değilse ..."
anre
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.